home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2004 #11 / Amiga Plus CD - 2004 - No. 11.iso / AmiSoft / Dev / e / q-device_src.lha / Q-Device.e < prev    next >
Text File  |  2004-08-12  |  105KB  |  2,345 lines

  1. OPT PREPROCESS, OSVERSION=37
  2.  
  3. /*
  4.     Program:     Q-Device1
  5.     Version:     V0.5
  6.     Author:      Ian Chapman
  7.     Description: A low-level SCSI query, command and diagnostic tool.
  8.  
  9.     LICENSE: Permission is granted to use this source code in whole or in part,
  10.              providing that the author (Ian Chapman) is credited in your project
  11.              in either the documentation, or the program itself. This applies to
  12.              both free and commercial software. In the case of commerical
  13.              software (including ShareWare), I am entitled to a free, fully
  14.              functional copy of the software.
  15.  
  16.              NO WARRANTY EITHER EXPRESSED OR IMPLIED AS TO THE FITNESS OF THIS
  17.              CODE FOR ANY PURPOSE. ALL USE IS ENTIRELY AND WHOLLY AT YOUR OWN
  18.              RISK
  19. */
  20.  
  21. MODULE  'exec/ports',
  22.         'exec/io',
  23.         'exec/execbase',
  24.         'exec/lists',
  25.         'exec/nodes',
  26.         'exec/tasks',
  27.         'exec/memory',
  28.         'amigalib/io',
  29.         'amigalib/boopsi',
  30.         'devices/scsidisk',
  31.         'mui/betterstring_mcc',
  32.         'libraries/mui',
  33.         'libraries/gadtools',
  34.         'utility/tagitem',
  35.         'utility/hooks',
  36.         'tools/installhook',
  37.         'dos/dos',
  38.         'dos/dosextens',
  39.         'miami/netinclude/pragmas/socket',
  40.         'amitcp/sys/ioctl',
  41.         'amitcp/sys/socket',
  42.         'amitcp/sys/types',
  43.         'amitcp/sys/time',
  44.         'amitcp/netdb',
  45.         'amitcp/netinet/in',
  46.         'muimaster',
  47.         'icon',
  48.         '*opcodes',
  49.         '*params',
  50.         '*headers'
  51.  
  52. CONST BUFFSIZE=255
  53. ENUM ID_INQUIRE=1, ID_EJECT, ID_INSERT, ID_LOCK, ID_UNLOCK, ID_CAPACITY, ID_TESTREADY, ID_READTOC,
  54.      ID_POWERUP, ID_POWERDOWN, ID_PROBE, ID_ABOUT, ID_MUIABOUT, ID_ICONIFY, ID_MUISET, ID_DIAGNOSTIC,
  55.      ID_MODESENSE, ID_DOUBLECLICK, ID_PREFS, ID_SAVEPREF, ID_USEPREF, ID_CANCELPREF, ID_SERIAL, ID_ATIP,
  56.      ID_SHOWLOGS
  57.  
  58. ENUM AFLG_INQUIRY_SILENT=10, AFLG_INQUIRY_VERBOSE, AFLG_INQUIRY_PROBE, AFLG_INQUIRY_SERIAL, AFLG_CAPTURE
  59.  
  60. ENUM NORMAL=0, ERR_MP=1, ERR_IOR, ERR_DEVICE, ERR_NOMUI, ERR_NOICON, ERR_NOAPP,
  61.      ERR_NOBSD, ERR_NOSOCK, ERR_NOCONNECT, ERR_REMOTESCSI
  62.  
  63. ENUM OBID_DRIVER=1, OBID_UNIT, OBID_PROBEFROM, OBID_PROBETO, OBID_HOST, OBID_PORT
  64.  
  65. OBJECT listentry -> Entries for the listview
  66. field
  67. value
  68. driver
  69. unit
  70. ENDOBJECT
  71.  
  72. DEF app, mui_output_lst, mui_output_lv, mui_status_tb, mui_device_tb,
  73.     mui_unit_tb, displayhook:hook, constructhook:hook, destructhook:hook,
  74.     devicelist[50]:ARRAY OF LONG, execobject:PTR TO execbase, global_devtype=0,
  75.     host[80]:STRING, port[5]:STRING, driver[80]:STRING, unit[6]:STRING
  76.  
  77. PROC main() HANDLE
  78. DEF signal, result, running=TRUE,   probefrom[6]:STRING, probeto[6]:STRING, probefromtemp[6]:STRING,
  79.     probetotemp[6]:STRING, mui_probefrom_tb, mui_probeto_tb, mui_host_tb, mui_port_tb,  mui_main_win,
  80.     mui_prefs_win, mui_inquire_but, mui_eject_but, mui_insert_but, mui_lock_but, mui_unlock_but,
  81.     mui_capacity_but, mui_testready_but, mui_readtoc_but, mui_powerup_but, mui_powerdown_but,
  82.     mui_probe_but, mui_diagnostic_but,  mui_modesense_but, mui_diagnostic_cyc, mui_prefsave_but,
  83.     mui_prefuse_but, mui_prefcancel_but, mui_serial_but, mui_atip_but, mui_showlogs_but, menu,
  84.     diagflag=0, diskobj=NIL, i, task:PTR TO process, icon[255]:STRING
  85.  
  86.     grab_devices()
  87.     menu:= [ NM_TITLE, 0, 'Project', 0, 0, 0, 0,
  88.              NM_ITEM,  0, 'About...', '?', 0, 0, ID_ABOUT,
  89.              NM_ITEM,  0, 'About MUI...', 0, 0, 0, ID_MUIABOUT,
  90.              NM_ITEM,  0, NM_BARLABEL, 0, 0, 0, 0,
  91.              NM_ITEM,  0, 'Iconify', 'I', 0, 0, ID_ICONIFY,
  92.              NM_ITEM,  0, 'Quit', 'Q', 0, 0, MUIV_Application_ReturnID_Quit,
  93.              NM_TITLE, 0, 'Query', 0, 0, 0, 0,
  94.              NM_ITEM,  0, 'Probe', 0, 0, 0, ID_PROBE,
  95.              NM_ITEM,  0, 'Full Inquiry', 0, 0, 0, ID_INQUIRE,
  96.              NM_ITEM,  0, 'Capacity', 0, 0, 0, ID_CAPACITY,
  97.              NM_ITEM,  0, 'Test Ready', 0, 0, 0, ID_TESTREADY,
  98.              NM_ITEM,  0, 'Device Parameters', 0, 0, 0, ID_MODESENSE,
  99.              NM_ITEM,  0, 'Show Firmware Logs', 0, 0, 0, ID_SHOWLOGS,
  100.              NM_ITEM,  0, 'Serial #', 0, 0, 0, ID_SERIAL,
  101.              NM_ITEM,  0, 'Read TOC', 0, 0, 0, ID_READTOC,
  102.              NM_ITEM,  0, 'ATIP', 0, 0, 0, ID_ATIP,  
  103.              NM_TITLE, 0, 'Control', 0, 0, 0, 0,
  104.              NM_ITEM,  0, 'Power Up', 0, 0, 0, ID_POWERUP,
  105.              NM_ITEM,  0, 'Power Down', 0, 0, 0, ID_POWERDOWN,
  106.              NM_ITEM,  0, 'Lock', 0, 0, 0, ID_LOCK,
  107.              NM_ITEM,  0, 'UnLock', 0, 0, 0, ID_UNLOCK,
  108.              NM_ITEM,  0, 'Insert', 0, 0, 0, ID_INSERT,
  109.              NM_ITEM,  0, 'Eject', 0, 0, 0, ID_EJECT,
  110.              NM_TITLE, 0, 'Diagnostic', 0, 0, 0, 0,
  111.              NM_ITEM,  0, 'Unit Self Test', 0, 0, 0, ID_DIAGNOSTIC,
  112.              NM_TITLE, 0, 'Settings', 0, 0, 0, 0,
  113.              NM_ITEM,  0, 'MUI Settings', 0, 0, 0, ID_MUISET,
  114.              NM_ITEM,  0, 'Preferences', 'P', 0, 0, ID_PREFS,
  115.              NM_ITEM,  0, NM_BARLABEL, 0, 0, 0, 0,
  116.              NM_ITEM,  0, 'Save Preferences', 0, 0, 0, ID_SAVEPREF,
  117.              NM_END,   0, NIL, 0, 0, 0, 0]:newmenu
  118.     
  119.     ->Quick hack to use program icon as AppIcon. A bit limited if Q-Device! is
  120.     ->launched from the CLI
  121.     Forbid()
  122.     task:=FindTask(NIL)
  123.     IF StrCmp(task.task.ln.name, 'Shell Process') = TRUE THEN StrCopy(icon, 'PROGDIR:Q-Device') ELSE StringF(icon, 'PROGDIR:\s', task.task.ln.name)
  124.     Permit()
  125.     
  126.     IF (muimasterbase:=OpenLibrary('muimaster.library', 19))=NIL THEN Raise(ERR_NOMUI)
  127.     IF (iconbase:=OpenLibrary('icon.library', 33))=NIL THEN Raise(ERR_NOICON)
  128.  
  129.     installhook(displayhook, {disp})
  130.     installhook(constructhook, {construct})
  131.     installhook(destructhook, {destruct})
  132.  
  133.     mui_output_lv:=ListviewObject,
  134.                     MUIA_Listview_Input, MUI_TRUE,
  135.                     MUIA_CycleChain, 1,
  136.                     MUIA_Listview_List, mui_output_lst:=ListObject,
  137.                         ReadListFrame,
  138.                             MUIA_List_Title, MUI_TRUE,
  139.                             MUIA_List_Format, 'BAR,',
  140.                             MUIA_List_DisplayHook, displayhook,
  141.                             MUIA_List_ConstructHook, constructhook, ->MUIV_List_ConstructHook_String,
  142.                             MUIA_List_DestructHook, destructhook, ->MUIV_List_DestructHook_String,
  143.                             MUIA_ShortHelp, 'Information and diagnostic output',
  144.                         End, -> ReadListFrame
  145.                     End ->Listviewobject
  146.  
  147.     mui_inquire_but:=make_button('Full Inquiry', 'Display full inquiry information')
  148.     mui_serial_but:=make_button('Serial #', 'Show product serial number')
  149.     mui_eject_but:=make_button('Eject', 'Attempt to eject media')
  150.     mui_insert_but:=make_button('Insert', 'Attempt to insert media')
  151.     mui_lock_but:=make_button('Lock', 'Prevent media from being removed')
  152.     mui_unlock_but:=make_button('UnLock', 'Allow media to be removed')
  153.     mui_capacity_but:=make_button('Capacity', 'Show device capacity')
  154.     mui_testready_but:=make_button('Test Ready', 'Test if unit is ready')
  155.     mui_readtoc_but:=make_button('Read TOC', 'Show CD Table of Contents')
  156.     mui_powerup_but:=make_button('Power Up', 'Attempt to spin-up the device')
  157.     mui_powerdown_but:=make_button('Power Down', 'Attempt to spin-down the device')
  158.     mui_probe_but:=make_button('\eb\eiProbe\en', 'Probe driver for attached devices')
  159.     mui_diagnostic_but:=make_button('Start Self Test', 'Instruct the device to perform a self test')
  160.     mui_modesense_but:=make_button('Device Parameters', 'Return information about the device\as parameters and specs')
  161.     mui_atip_but:=make_button('ATIP', 'Show ATIP information for CD-R/RW')
  162.     mui_showlogs_but:=make_button('Show Firmware Logs', 'Attempt to display and decode all firmware logs.')
  163.  
  164.     mui_prefsave_but:=make_button('Save', 'Save preferences')
  165.     mui_prefuse_but:=make_button('Use', 'Use preferences, changes are lost after reboot')
  166.     mui_prefcancel_but:=make_button('Cancel', 'Discard any changes')
  167.  
  168.  
  169.     mui_diagnostic_cyc:=make_keycycle(['Simple 1', 'Simple 2', 'Deep 1', 'Deep 2', NIL], "t", 'Choose diagnostic test')
  170.  
  171.     mui_device_tb:=BetterStringObject, StringFrame,
  172.                     MUIA_String_AdvanceOnCR, MUI_TRUE,
  173.                     MUIA_String_Contents, driver,
  174.                     MUIA_ShortHelp, 'Device driver to use',
  175.                     MUIA_CycleChain, 1,
  176.                     MUIA_ObjectID, OBID_DRIVER,
  177.                    End
  178.  
  179.     mui_unit_tb:=BetterStringObject, StringFrame,
  180.                     MUIA_String_AdvanceOnCR, MUI_TRUE,
  181.                     MUIA_String_Contents, unit,
  182.                     MUIA_ShortHelp, 'AmigaDOS Unit Number',
  183.                     MUIA_String_Accept, '0123456789',
  184.                     MUIA_String_MaxLen, 6,
  185.                     MUIA_CycleChain, 1,
  186.                     MUIA_ObjectID, OBID_UNIT,
  187.                  End
  188.  
  189.     mui_status_tb:=TextObject, TextFrame,
  190.                     MUIA_String_Contents, 'Ready',
  191.                     MUIA_ShortHelp, 'SCSI/IDE target condition',
  192.                    End
  193.  
  194.     mui_probefrom_tb:=BetterStringObject, StringFrame,
  195.                     MUIA_String_AdvanceOnCR, MUI_TRUE,
  196.                     MUIA_String_Contents, probefrom,
  197.                     MUIA_ShortHelp, 'Probing devices starts at this unit',
  198.                     MUIA_String_Accept, '0123456789',
  199.                     MUIA_String_MaxLen, 6,
  200.                     MUIA_CycleChain, 1,
  201.                     MUIA_ObjectID, OBID_PROBEFROM,
  202.                  End
  203.  
  204.     mui_probeto_tb:=BetterStringObject, StringFrame,
  205.                     MUIA_String_AdvanceOnCR, MUI_TRUE,
  206.                     MUIA_String_Contents, probeto,
  207.                     MUIA_ShortHelp, 'Probing devices ends at this unit',
  208.                     MUIA_String_Accept, '0123456789',
  209.                     MUIA_String_MaxLen, 6,
  210.                     MUIA_CycleChain, 1,
  211.                     MUIA_ObjectID, OBID_PROBETO,
  212.                  End
  213.  
  214.     mui_host_tb:=BetterStringObject, StringFrame,
  215.                     MUIA_String_AdvanceOnCR, MUI_TRUE,
  216.                     MUIA_String_Contents, host,
  217.                     MUIA_ShortHelp, 'Host to connect to when using tcpip-scsi.device',
  218.                     MUIA_String_MaxLen, 80,
  219.                     MUIA_CycleChain, 1,
  220.                     MUIA_ObjectID, OBID_HOST,
  221.                  End
  222.  
  223.     mui_port_tb:=BetterStringObject, StringFrame,
  224.                     MUIA_String_AdvanceOnCR, MUI_TRUE,
  225.                     MUIA_String_Contents, port,
  226.                     MUIA_ShortHelp, 'Base port to connect to when using tcpip-scsi.device',
  227.                     MUIA_String_MaxLen, 5,
  228.                     MUIA_CycleChain, 1,
  229.                     MUIA_ObjectID, OBID_PORT,
  230.                  End
  231.  
  232.  
  233.     app:=ApplicationObject,
  234.         MUIA_Application_Title      , 'Q-Device!',
  235.         MUIA_Application_Version    , '$VER: Q-Device! v0.5',
  236.         MUIA_Application_Copyright  , 'Written By Ian Chapman (2003)',
  237.         MUIA_Application_Author     , 'Ian Chapman',
  238.         MUIA_Application_Description, 'IDE/SCSI device query tool',
  239.         MUIA_Application_Base       , 'QDEVICE',
  240.         MUIA_Application_SingleTask , FALSE,
  241.         MUIA_Application_DiskObject , diskobj:=GetDiskObject(icon),
  242.         MUIA_Application_Menustrip  , Mui_MakeObjectA(MUIO_MenustripNM,[menu,0]),
  243.         MUIA_Application_HelpFile   , 'Q-Device!.guide',
  244.  
  245.         SubWindow, mui_main_win:=WindowObject,
  246.         MUIA_Window_Title       , 'Q-Device! V0.5 by Ian Chapman',
  247.         MUIA_Window_ID          , "QDEV",
  248.         MUIA_Window_Activate    , MUI_TRUE,
  249.  
  250.         WindowContents, VGroup,
  251.                         Child, HGroup,
  252.                             Child, Label('Driver:'),
  253.                             Child, PoplistObject,
  254.                                     MUIA_Popstring_String, mui_device_tb,
  255.                                     MUIA_Popstring_Button, PopButton( MUII_PopUp ),
  256.                                     MUIA_Poplist_Array, devicelist,
  257.                             End,
  258.                             Child, Label('Unit:'),                            
  259.                             Child, PoplistObject,
  260.                                     MUIA_Popstring_String, mui_unit_tb,
  261.                                     MUIA_Popstring_Button, PopButton( MUII_PopUp ),
  262.                                     MUIA_Poplist_Array, ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', NIL],
  263.                             End,
  264.                         End, ->HGroup
  265.                         Child, HGroup,
  266.                             Child, Label('Target Status:'),
  267.                             Child, mui_status_tb,
  268.                         End, -> HGroup
  269.                         Child, RegisterGroup(['Query', 'Control', 'Diagnostic', NIL]),
  270.                             Child, VGroup,
  271.                                 Child, ColGroup(3), 
  272.                                     Child, mui_probe_but,
  273.                                     Child, mui_inquire_but,
  274.                                     Child, mui_capacity_but,
  275.                                     Child, mui_testready_but,
  276.                                     Child, mui_modesense_but,
  277.                                     Child, mui_showlogs_but,
  278.                                     Child, mui_serial_but,
  279.                                     Child, mui_readtoc_but,
  280.                                     Child, mui_atip_but,   
  281.                                 End, -> ColGroup
  282.                             End, -> VGroup
  283.                             Child, ColGroup(2),
  284.                                 Child, mui_powerup_but,
  285.                                 Child, mui_powerdown_but,
  286.                                 Child, mui_lock_but,
  287.                                 Child, mui_unlock_but,
  288.                                 Child, mui_insert_but,
  289.                                 Child, mui_eject_but,
  290.                             End, -> Colgroup
  291.                             Child, ColGroup(2), GroupFrameT('Diagnostic Tests'),
  292.                                 Child, HGroup,
  293.                                     Child, Label('_Test Type:'),
  294.                                     Child, mui_diagnostic_cyc,
  295.                                 End, -> HGroup
  296.                                 Child, mui_diagnostic_but,
  297.                             End, -> ColGroup
  298.                         End, -> Register,
  299.                         Child, BalanceObject, End,
  300.                         Child, mui_output_lv,
  301.                     End, ->VGroup
  302.                     
  303.                 End, -> WindowObject
  304.  
  305.         SubWindow, mui_prefs_win:=WindowObject,
  306.         MUIA_Window_Title       , 'Preferences',
  307.         MUIA_Window_ID          , "PREF",
  308.         MUIA_Window_Activate    , MUI_TRUE,
  309.         MUIA_HelpNode           , 'Preferences Window',
  310.  
  311.         WindowContents, VGroup,
  312.                             Child, ColGroup(2),
  313.                                 Child, Label('Probe Units From:'),
  314.                                 Child, HGroup,
  315.                                     Child, mui_probefrom_tb,
  316.                                     Child, Label('To:'),
  317.                                     Child, mui_probeto_tb,
  318.                                 End, -> HGroup
  319.                             End, -> ColGroup
  320.                             Child, HGroup,
  321.                                 GroupFrameT('tcpip-scsi.device'),
  322.                                 Child, Label('Host:'),
  323.                                 Child, mui_host_tb,
  324.                                 Child, Label('Base Port:'),
  325.                                 Child, mui_port_tb,
  326.                             End, -> HGroup  
  327.                             Child, BalanceObject, End,
  328.                             Child, HGroup,
  329.                                 Child, mui_prefsave_but,
  330.                                 Child, mui_prefuse_but,
  331.                                 Child, mui_prefcancel_but,
  332.                             End, -> HGroup
  333.                         End, -> VGroup
  334.         End, -> Window
  335.  
  336.     End -> Application
  337.  
  338.     IF (app=NIL) THEN Raise(ERR_NOAPP)
  339.  
  340.     doMethodA(mui_inquire_but,      [MUIM_Notify, MUIA_Pressed, FALSE, app, 2, MUIM_Application_ReturnID, ID_INQUIRE])
  341.     doMethodA(mui_serial_but,       [MUIM_Notify, MUIA_Pressed, FALSE, app, 2, MUIM_Application_ReturnID, ID_SERIAL])
  342.     doMethodA(mui_eject_but,        [MUIM_Notify, MUIA_Pressed, FALSE, app, 2, MUIM_Application_ReturnID, ID_EJECT])
  343.     doMethodA(mui_insert_but,       [MUIM_Notify, MUIA_Pressed, FALSE, app, 2, MUIM_Application_ReturnID, ID_INSERT])
  344.     doMethodA(mui_lock_but,         [MUIM_Notify, MUIA_Pressed, FALSE, app, 2, MUIM_Application_ReturnID, ID_LOCK])
  345.     doMethodA(mui_unlock_but,       [MUIM_Notify, MUIA_Pressed, FALSE, app, 2, MUIM_Application_ReturnID, ID_UNLOCK])
  346.     doMethodA(mui_capacity_but,     [MUIM_Notify, MUIA_Pressed, FALSE, app, 2, MUIM_Application_ReturnID, ID_CAPACITY])
  347.     doMethodA(mui_testready_but,    [MUIM_Notify, MUIA_Pressed, FALSE, app, 2, MUIM_Application_ReturnID, ID_TESTREADY])
  348.     doMethodA(mui_readtoc_but,      [MUIM_Notify, MUIA_Pressed, FALSE, app, 2, MUIM_Application_ReturnID, ID_READTOC])
  349.     doMethodA(mui_powerup_but,      [MUIM_Notify, MUIA_Pressed, FALSE, app, 2, MUIM_Application_ReturnID, ID_POWERUP])
  350.     doMethodA(mui_powerdown_but,    [MUIM_Notify, MUIA_Pressed, FALSE, app, 2, MUIM_Application_ReturnID, ID_POWERDOWN])
  351.     doMethodA(mui_probe_but,        [MUIM_Notify, MUIA_Pressed, FALSE, app, 2, MUIM_Application_ReturnID, ID_PROBE])
  352.     doMethodA(mui_diagnostic_but,   [MUIM_Notify, MUIA_Pressed, FALSE, app, 2, MUIM_Application_ReturnID, ID_DIAGNOSTIC])
  353.     doMethodA(mui_modesense_but,    [MUIM_Notify, MUIA_Pressed, FALSE, app, 2, MUIM_Application_ReturnID, ID_MODESENSE])
  354.     doMethodA(mui_atip_but,         [MUIM_Notify, MUIA_Pressed, FALSE, app, 2, MUIM_Application_ReturnID, ID_ATIP])
  355.     doMethodA(mui_showlogs_but,     [MUIM_Notify, MUIA_Pressed, FALSE, app, 2, MUIM_Application_ReturnID, ID_SHOWLOGS])
  356.     doMethodA(mui_prefsave_but,     [MUIM_Notify, MUIA_Pressed, FALSE, app, 2, MUIM_Application_ReturnID, ID_SAVEPREF])
  357.     doMethodA(mui_prefuse_but,      [MUIM_Notify, MUIA_Pressed, FALSE, app, 2, MUIM_Application_ReturnID, ID_USEPREF])
  358.     doMethodA(mui_prefcancel_but,   [MUIM_Notify, MUIA_Pressed, FALSE, app, 2, MUIM_Application_ReturnID, ID_CANCELPREF])
  359.     doMethodA(mui_diagnostic_cyc,   [MUIM_Notify, MUIA_Cycle_Active, MUIV_EveryTime, mui_diagnostic_cyc, 3, MUIM_WriteLong, MUIV_TriggerValue, {diagflag}])
  360.     doMethodA(mui_device_tb,        [MUIM_Notify, MUIA_String_Contents, MUIV_EveryTime, mui_device_tb,    3, MUIM_WriteString, MUIV_TriggerValue, driver])
  361.     doMethodA(mui_unit_tb,          [MUIM_Notify, MUIA_String_Contents, MUIV_EveryTime, mui_unit_tb,      3, MUIM_WriteString, MUIV_TriggerValue, unit])
  362.     doMethodA(mui_probefrom_tb,     [MUIM_Notify, MUIA_String_Contents, MUIV_EveryTime, mui_probefrom_tb, 3, MUIM_WriteString, MUIV_TriggerValue, probefrom])
  363.     doMethodA(mui_probeto_tb,       [MUIM_Notify, MUIA_String_Contents, MUIV_EveryTime, mui_probeto_tb,   3, MUIM_WriteString, MUIV_TriggerValue, probeto])
  364.     doMethodA(mui_host_tb,          [MUIM_Notify, MUIA_String_Contents, MUIV_EveryTime, mui_host_tb,      3, MUIM_WriteString, MUIV_TriggerValue, host])
  365.     doMethodA(mui_port_tb,          [MUIM_Notify, MUIA_String_Contents, MUIV_EveryTime, mui_port_tb,      3, MUIM_WriteString, MUIV_TriggerValue, port])
  366.     doMethodA(mui_main_win,         [MUIM_Notify, MUIA_Window_CloseRequest, MUI_TRUE, app, 2, MUIM_Application_ReturnID, MUIV_Application_ReturnID_Quit])
  367.     doMethodA(mui_prefs_win,        [MUIM_Notify, MUIA_Window_CloseRequest, MUI_TRUE, app, 2, MUIM_Application_ReturnID, ID_CANCELPREF])
  368.     doMethodA(mui_output_lv,        [MUIM_Notify, MUIA_Listview_DoubleClick, MUI_TRUE, app, 2, MUIM_Application_ReturnID, ID_DOUBLECLICK])
  369.     set(mui_status_tb, MUIA_Text_Contents, 'Ready')
  370.     SetAttrsA(mui_main_win, [MUIA_Window_ActiveObject, mui_unit_tb, MUIA_Window_Open, MUI_TRUE, TAG_DONE])
  371.  
  372.     doMethodA(app, [MUIM_Application_Load, MUIV_Application_Load_ENV])
  373.  
  374.     IF (StrCmp(unit, '', ALL) = TRUE)
  375.         StrCopy(unit, '0')
  376.         set(mui_unit_tb, MUIA_String_Contents, '0')
  377.     ENDIF
  378.  
  379.     IF (StrCmp(driver, '', ALL) = TRUE)
  380.         StrCopy(driver, 'scsi.device')
  381.         set(mui_device_tb, MUIA_String_Contents, driver)
  382.     ENDIF
  383.  
  384.     IF (StrCmp(probefrom, '', ALL) = TRUE)
  385.         StrCopy(probefrom, '0')
  386.         set(mui_probefrom_tb, MUIA_String_Contents, '0')
  387.     ENDIF
  388.  
  389.     IF (StrCmp(probeto, '', ALL) = TRUE)
  390.         StrCopy(probeto, '12')
  391.         set(mui_probeto_tb, MUIA_String_Contents, '15')
  392.     ENDIF
  393.  
  394.     IF (StrCmp(host, '', ALL) = TRUE)
  395.         StrCopy(host, 'localhost')
  396.         set(mui_host_tb, MUIA_String_Contents, 'localhost')
  397.     ENDIF
  398.  
  399.     IF (StrCmp(port, '', ALL) = TRUE)
  400.         StrCopy(port, '8000')
  401.         set(mui_port_tb, MUIA_String_Contents, '8000')
  402.     ENDIF
  403.  
  404.     WHILE running
  405.         result:=doMethodA(app, [MUIM_Application_Input,{signal}])
  406.         SELECT result
  407.             CASE MUIV_Application_ReturnID_Quit
  408.                 running:=FALSE
  409.             CASE ID_SAVEPREF
  410.                 doMethodA(app, [MUIM_Application_Save, MUIV_Application_Save_ENV])
  411.                 doMethodA(app, [MUIM_Application_Save, MUIV_Application_Save_ENVARC])
  412.                 set(mui_prefs_win, MUIA_Window_Open, FALSE)
  413.             CASE ID_USEPREF
  414.                 doMethodA(app, [MUIM_Application_Save, MUIV_Application_Save_ENV])
  415.                 set(mui_prefs_win, MUIA_Window_Open, FALSE)
  416.             CASE ID_CANCELPREF
  417.                 StrCopy(probefrom, probefromtemp)
  418.                 StrCopy(probeto, probetotemp)
  419.                 set(mui_prefs_win, MUIA_Window_Open, FALSE)
  420.                 set(mui_probeto_tb, MUIA_String_Contents, probeto)
  421.                 set(mui_probefrom_tb, MUIA_String_Contents, probefrom)
  422.             CASE ID_PREFS
  423.                 StrCopy(probefromtemp, probefrom)
  424.                 StrCopy(probetotemp, probeto)
  425.                 set(mui_prefs_win, MUIA_Window_Open, MUI_TRUE)
  426.             CASE ID_INQUIRE
  427.                 doMethodA(mui_output_lst, [MUIM_List_Clear])
  428.                 query(driver, Val(unit), [SCSI_INQUIRY, 0, 0, 0, BUFFSIZE,0]:cdb6, SIZEOF cdb6, AFLG_INQUIRY_VERBOSE)
  429.             CASE ID_SERIAL
  430.                 doMethodA(mui_output_lst, [MUIM_List_Clear])
  431.                 query(driver, Val(unit), [SCSI_INQUIRY, 1, $80, 0, BUFFSIZE, 0]:cdb6, SIZEOF cdb6, AFLG_INQUIRY_SERIAL)
  432.             CASE ID_EJECT
  433.                 doMethodA(mui_output_lst, [MUIM_List_Clear])
  434.                 query(driver, Val(unit), [SCSI_CD_START_STOP_UNIT, 0, 0, 0, P_EJECT, 0]:cdb6, SIZEOF cdb6, NIL)
  435.             CASE ID_INSERT
  436.                 doMethodA(mui_output_lst, [MUIM_List_Clear])
  437.                 query(driver, Val(unit), [SCSI_CD_START_STOP_UNIT, 0, 0, 0, P_INSERT, 0]:cdb6, SIZEOF cdb6, NIL)
  438.             CASE ID_POWERUP
  439.                 doMethodA(mui_output_lst, [MUIM_List_Clear])
  440.                 query(driver, Val(unit), [SCSI_DA_START_STOP_UNIT, 0, 0, 0, P_START, 0]:cdb6, SIZEOF cdb6, NIL)
  441.             CASE ID_POWERDOWN
  442.                 doMethodA(mui_output_lst, [MUIM_List_Clear])
  443.                 query(driver, Val(unit), [SCSI_DA_START_STOP_UNIT, 0, 0, 0, P_STOP, 0]:cdb6, SIZEOF cdb6, NIL)
  444.             CASE ID_LOCK
  445.                 doMethodA(mui_output_lst, [MUIM_List_Clear])
  446.                 query(driver, Val(unit), [SCSI_CD_PREVENT_ALLOW_MEDIUM_REMOVAL, 0, 0, 0, P_LOCK, 0]:cdb6, SIZEOF cdb6, NIL)
  447.             CASE ID_UNLOCK
  448.                 doMethodA(mui_output_lst, [MUIM_List_Clear])
  449.                 query(driver, Val(unit), [SCSI_CD_PREVENT_ALLOW_MEDIUM_REMOVAL, 0, 0, 0, P_UNLOCK, 0]:cdb6, SIZEOF cdb6, NIL)
  450.             CASE ID_CAPACITY
  451.                 doMethodA(mui_output_lst, [MUIM_List_Clear])
  452.                 query(driver, Val(unit), [SCSI_DA_READ_CAPACITY, 0, 0, 0, 0, 0, 0, 0, 0, 0]:cdb10, SIZEOF cdb10, NIL)
  453.             CASE ID_TESTREADY
  454.                 doMethodA(mui_output_lst, [MUIM_List_Clear])
  455.                 query(driver, Val(unit), [SCSI_TEST_UNIT_READY, 0, 0, 0, 0, 0]:cdb6, SIZEOF cdb6, NIL)
  456.             CASE ID_READTOC
  457.                 doMethodA(mui_output_lst, [MUIM_List_Clear])
  458.                 query(driver, Val(unit), [SCSI_CD_READ_TOC, 0, 0, 0, 0, 0, 1, 0, BUFFSIZE, 0]:cdb10, SIZEOF cdb10, NIL)
  459.             CASE ID_ATIP
  460.                 doMethodA(mui_output_lst, [MUIM_List_Clear])
  461.                 query(driver, Val(unit), [SCSI_CD_READ_TOC, 0, %00000100, 0, 0, 0, 0, 0, BUFFSIZE, 0]:cdb10, SIZEOF cdb10, NIL)
  462.             CASE ID_SHOWLOGS
  463.                 doMethodA(mui_output_lst, [MUIM_List_Clear])
  464.                 query(driver, Val(unit), [SCSI_LOG_SENSE, 0, P_LOG_LIST, 0, 0, 0, 0, 0, BUFFSIZE, 0]:cdb10, SIZEOF cdb10, NIL)
  465.                 ->query(driver, Val(unit), [SCSI_LOG_SENSE, 0, 0, 0, 0, 0, 0, 0, BUFFSIZE, 0]:cdb10, SIZEOF cdb10, NIL)
  466.  
  467.  
  468.             CASE ID_PROBE
  469.                 doMethodA(mui_output_lst, [MUIM_List_Clear])
  470.                 IF Val(probefrom) > Val(probeto)
  471.                     FOR i:=Val(probefrom) TO Val(probeto) STEP -1 DO query(driver, i, [SCSI_INQUIRY, 0, 0, 0, BUFFSIZE, 0]:cdb6, SIZEOF cdb6, AFLG_INQUIRY_PROBE)
  472.                 ELSE
  473.                     FOR i:=Val(probefrom) TO Val(probeto) DO query(driver, i, [SCSI_INQUIRY, 0, 0, 0, BUFFSIZE, 0]:cdb6, SIZEOF cdb6, AFLG_INQUIRY_PROBE)
  474.                 ENDIF
  475.             CASE ID_DIAGNOSTIC
  476.                 doMethodA(mui_output_lst, [MUIM_List_Clear])
  477.                 SELECT diagflag
  478.                     CASE 0
  479.                         query(driver, Val(unit), [SCSI_SEND_DIAGNOSTIC, P_DIAG_SIMPLE1, 0, 0, 0, 0]:cdb6, SIZEOF cdb6, NIL)
  480.                     CASE 1
  481.                         query(driver, Val(unit), [SCSI_SEND_DIAGNOSTIC, P_DIAG_SIMPLE2, 0, 0, 0, 0]:cdb6, SIZEOF cdb6, NIL)
  482.                     CASE 2
  483.                         IF Mui_RequestA(app, mui_main_win, 0, 'Warning!', '_Proceed|*_Cancel', 'A deep test may require the device to take itself offline temporarily\nor make temporary changes to the medium. It is highly recommended\nyou make sure nothing else is accessing the device before performing\nthis test.', NIL)<>0
  484.                             query(driver, Val(unit), [SCSI_SEND_DIAGNOSTIC, P_DIAG_COMPLEX1, 0, 0, 0, 0]:cdb6, SIZEOF cdb6, NIL)
  485.                         ENDIF
  486.                     CASE 3
  487.                         IF Mui_RequestA(app, mui_main_win, 0, 'Warning!', '_Proceed|*_Cancel', 'A deep test may require the device to take itself offline temporarily\nor make temporary changes to the medium. It is highly recommended\nyou make sure nothing else is accessing the device before performing\nthis test.', NIL)<>0
  488.                             query(driver, Val(unit), [SCSI_SEND_DIAGNOSTIC, P_DIAG_COMPLEX2, 0, 0, 0, 0]:cdb6, SIZEOF cdb6, NIL)
  489.                         ENDIF
  490.                 ENDSELECT
  491.             CASE ID_MODESENSE
  492.                 doMethodA(mui_output_lst, [MUIM_List_Clear])
  493.                 IF query(driver, Val(unit), [SCSI_INQUIRY, 0, 0, 0, BUFFSIZE, 0]:cdb6, SIZEOF cdb6, AFLG_INQUIRY_SILENT) = 0
  494.                    IF query(driver, Val(unit), [SCSI_MODE_SENSE_6, 0, P_ALLPAGES, 0, BUFFSIZE, 0]:cdb6, SIZEOF cdb6, NIL) <> 0
  495.                        query(driver, Val(unit), [SCSI_MODE_SENSE_10, 0, P_ALLPAGES, 0, 0, 0, 0, 0, BUFFSIZE, 0]:cdb10, SIZEOF cdb10, NIL)
  496.                    ENDIF
  497.                 ENDIF
  498.             CASE ID_ABOUT
  499.                 Mui_RequestA(app, mui_main_win, 0, 'About Q-Device!','*_OK','\ecQ-Device! 0.5 by Ian Chapman (2003-2004)\nVersion 0.5 \n\nA low-level SCSI/IDE query, control and diagnostic tool\n\n\ebUse of this software is entirely at YOUR OWN risk!\en', NIL)
  500.             CASE ID_MUIABOUT
  501.                 doMethodA(app, [MUIM_Application_AboutMUI, mui_main_win])
  502.             CASE ID_MUISET
  503.                 doMethodA(app, [MUIM_Application_OpenConfigWindow, 0])
  504.             CASE ID_ICONIFY
  505.                 set(app, MUIA_Application_Iconified, MUI_TRUE)
  506.             CASE ID_DOUBLECLICK
  507.                 click_inquiry()
  508.         ENDSELECT
  509.         IF (running AND signal) THEN Wait(signal)
  510.     ENDWHILE
  511.  
  512.     EXCEPT DO
  513.         IF (app) THEN Mui_DisposeObject(app)
  514.         IF (diskobj) THEN FreeDiskObject(diskobj)
  515.         IF (iconbase) THEN CloseLibrary(iconbase)
  516.         IF (muimasterbase) THEN CloseLibrary(muimasterbase)
  517.         SELECT exception
  518.             CASE NORMAL
  519.                 ->Normal Exit
  520.             CASE ERR_NOMUI
  521.                 PrintF('Unable to open muimaster.library V19+\n')
  522.             CASE ERR_NOICON
  523.                 PrintF('Unable to open icon.library V33+\n')
  524.             CASE ERR_NOAPP
  525.                 PrintF('Unable to create application\n')
  526.             DEFAULT
  527.                 PrintF('Unknown exception of type (\d)\n', exception)
  528.         ENDSELECT
  529. ENDPROC
  530.  
  531.  
  532. /*
  533. ** Procedure which distributes a query to the appropriate query procedure
  534. ** depending on whether it's a real SCSI device or the pseudo tcpip-scsi
  535. ** device. It is then responsible for distributing the results to the
  536. ** appropriate handler procedure for processing
  537. */
  538. PROC query(device:PTR TO CHAR, unit, cmd:PTR TO cdb12, size, aflg)
  539. DEF buffer=NIL, returncode=0, returnexcept=0
  540.  
  541.     buffer:=New(BUFFSIZE)
  542.  
  543.     IF StrCmp(device, 'tcpip-scsi.device')
  544.         returncode,returnexcept:=netquery(device, unit, cmd, size, buffer)
  545.     ELSE
  546.         returncode,returnexcept:=scsiquery(device, unit, cmd, size, buffer)
  547.     ENDIF
  548.  
  549.     IF returnexcept = 0
  550.  
  551.     SELECT returncode
  552.         CASE 0
  553.             IF cmd.opcode <> SCSI_REQUEST_SENSE THEN set(mui_status_tb, MUIA_Text_Contents, 'Target Response: GOOD')
  554.             SELECT $FF OF cmd.opcode
  555.                 CASE SCSI_CD_READ_TOC
  556.                     IF (Char(cmd+2) = 0) THEN process_toc(buffer) ELSE process_atip(buffer)
  557.                 CASE SCSI_TEST_UNIT_READY
  558.                     outlist_d('Unit Ready', device, unit)
  559.                 CASE SCSI_INQUIRY
  560.                     IF aflg=AFLG_INQUIRY_SERIAL
  561.                         process_serial(buffer)
  562.                     ELSE
  563.                         process_inquiry(device, unit, buffer, aflg)
  564.                     ENDIF
  565.                 CASE SCSI_DA_READ_CAPACITY
  566.                     process_capacity(buffer)
  567.                 CASE SCSI_CD_START_STOP_UNIT
  568.                     IF cmd.param4=P_EJECT
  569.                         outlist_d('Sent eject command', device, unit)
  570.                     ELSEIF cmd.param4=P_INSERT
  571.                         outlist_d('Sent insert command', device, unit)
  572.                     ELSEIF cmd.param4=P_START
  573.                         outlist_d('Sent power up command', device, unit)
  574.                     ELSEIF cmd.param4=P_STOP
  575.                         outlist_d('Sent power down command', device, unit)
  576.                     ENDIF
  577.                 CASE SCSI_CD_PREVENT_ALLOW_MEDIUM_REMOVAL
  578.                     IF cmd.param4=P_LOCK
  579.                         outlist_d('Sent lock command', device, unit)
  580.                     ELSE
  581.                         outlist_d('Sent unlock command', device, unit)
  582.                     ENDIF
  583.                 CASE SCSI_REQUEST_SENSE
  584.                     process_sense(buffer)
  585.                 CASE SCSI_MODE_SENSE_6
  586.                     process_modesense(buffer, size)
  587.                 CASE SCSI_MODE_SENSE_10
  588.                     process_modesense(buffer, size)
  589.                 CASE SCSI_LOG_SENSE
  590.                     SELECT $3F OF Char(buffer)
  591.                         CASE $0
  592.                             outlist('\ebLog Type:\en', 'List of supported log types')
  593.                             process_log_support(buffer)
  594.                         CASE $1
  595.                             process_log_buffer(buffer)
  596.                         CASE $2
  597.                             process_log_errors(buffer)
  598.                         CASE $3
  599.                             process_log_errors(buffer)
  600.                         CASE $4
  601.                             process_log_errors(buffer)
  602.                         CASE $5
  603.                             process_log_errors(buffer)
  604.                         CASE $6
  605.                             process_log_nmerrors(buffer)
  606.                         CASE $D
  607.                             process_log_temperature(buffer)
  608.                         CASE $2F
  609.                             process_log_ie(buffer)
  610.                     ENDSELECT
  611.                 CASE SCSI_SEND_DIAGNOSTIC
  612.                     outlist_d('Self Test Passed', device, unit)
  613.             ENDSELECT
  614.         CASE 2
  615.             
  616.             IF cmd.opcode <> SCSI_REQUEST_SENSE  -> Hopefully avoids recursive loops with bad devices/drivers which don't support request sense.
  617.                 set(mui_status_tb, MUIA_Text_Contents, 'Target Response: CHECK_CONDITION')
  618.                 outlist('\ebWarning:\en', 'Command generated an error response (see below)')
  619.                 query(device, unit, [SCSI_REQUEST_SENSE, 0, 0, 0, BUFFSIZE, 0]:cdb6, SIZEOF cdb6, NIL)
  620.             ENDIF
  621.             
  622.         CASE 4
  623.             set(mui_status_tb, MUIA_Text_Contents, 'Target Response: CONDITION_MET')
  624.         CASE 8
  625.             set(mui_status_tb, MUIA_Text_Contents, 'Target Response: BUSY')
  626.         CASE 16
  627.             set(mui_status_tb, MUIA_Text_Contents, 'Target Response: INTERMEDIATE')
  628.         CASE 20
  629.             set(mui_status_tb, MUIA_Text_Contents, 'Target Response: INTERMEDIATE_CONDITION_MET')
  630.         CASE 24
  631.             set(mui_status_tb, MUIA_Text_Contents, 'Target Response: RESERVATION_CONFLICT')
  632.         CASE 34
  633.             set(mui_status_tb, MUIA_Text_Contents, 'Target Response: COMMAND_TERMINATED')
  634.         CASE 72
  635.             set(mui_status_tb, MUIA_Text_Contents, 'Target Response: QUEUE_FULL')
  636.         DEFAULT
  637.             set(mui_status_tb, MUIA_Text_Contents, 'Target Response: UNKNOWN')
  638.     ENDSELECT
  639.     ENDIF
  640. ENDPROC
  641.  
  642.  
  643. /*
  644. ** Procedure for simply sending the SCSI command to the scsi device driver and
  645. ** writing the return data into the buffer for processing by the handler
  646. ** procedures
  647. */
  648. PROC scsiquery(device:PTR TO CHAR, unit, cmd:PTR TO cdb12, size, buffer) HANDLE
  649. DEF myport=NIL:PTR TO mp, ioreq=NIL:PTR TO iostd, scsiio:scsicmd, error=-1, status
  650.  
  651.     IF (myport:=CreateMsgPort())=NIL THEN Raise(ERR_MP)
  652.     IF (ioreq:=createStdIO(myport))=NIL THEN Raise(ERR_IOR)
  653.     IF (error:=OpenDevice(device, unit, ioreq, 0)) <> NIL THEN Raise(ERR_DEVICE)
  654.  
  655.     scsiio.data:=buffer
  656.     scsiio.length:=BUFFSIZE
  657.     scsiio.command:=cmd
  658.     scsiio.cmdlength:=size
  659.     scsiio.flags:=SCSIF_READ -> OR SCSIF_AUTOSENSE
  660.     scsiio.senseactual:=0
  661.     ioreq.command:=HD_SCSICMD
  662.     ioreq.data:=scsiio
  663.     ioreq.length:=SIZEOF scsicmd
  664.     DoIO(ioreq)
  665.     status:=ioreq.error
  666.  
  667.     SELECT status
  668.         CASE HFERR_SELFUNIT
  669.             outlist_d('<self issuing command error>', device, unit)
  670.         CASE HFERR_DMA
  671.             outlist_d('<DMA Failure>', device, unit)
  672.         CASE HFERR_PHASE
  673.             outlist_d('<illegal scsi phase>', device, unit)
  674.         CASE HFERR_PARITY
  675.             outlist_d('<parity error>', device, unit)
  676.         CASE HFERR_SELTIMEOUT
  677.             outlist_d('<device timed out>', device, unit)
  678.     ENDSELECT
  679.  
  680.     EXCEPT DO
  681.         IF error=NIL
  682.             IF  CheckIO(ioreq)<>NIL
  683.                 AbortIO(ioreq)
  684.                 WaitIO(ioreq)
  685.             ENDIF
  686.         ENDIF
  687.  
  688.     CloseDevice(ioreq)
  689.     IF ioreq <> NIL THEN deleteStdIO(ioreq)
  690.     IF myport <> NIL THEN DeleteMsgPort(myport)
  691.  
  692.     SELECT exception
  693.         CASE ERR_MP
  694.             outlist('\ebError:\en', 'Unable to create message port')
  695.         CASE ERR_IOR
  696.             outlist('\ebError:\en', 'Unable to create IORequest')
  697.         CASE ERR_DEVICE
  698.             outlist_d('<no device>', device, unit)
  699.     ENDSELECT
  700.  
  701. ENDPROC (scsiio.status AND %00111110), exception
  702.  
  703.  
  704. /*
  705. ** Procedure for sending the scsi command across the network to a remote
  706. ** helper daemon such as qdd, then writing the return data into the buffer for
  707. ** processing by the handler procedures
  708. */
  709. PROC netquery(device:PTR TO CHAR, unit, cmd:PTR TO cdb12, size, buffer) HANDLE
  710. DEF sock, sain:PTR TO sockaddr_in, received=0, returncode=0, hst:PTR TO hostent,
  711.     address:in_addr, saou:sockaddr_in, tv:timeval, readfds:fd_set
  712.  
  713.     IF (socketbase:=OpenLibrary('bsdsocket.library', NIL)) = NIL THEN Raise(ERR_NOBSD)
  714.     sain:=NewM(SIZEOF sockaddr_in, MEMF_PUBLIC OR MEMF_CLEAR)
  715.     IF (host[0] > 47) AND (host[0] < 58)
  716.         address.addr:=Inet_addr(host)
  717.         IF address.addr = INADDR_NONE THEN Raise(ERR_NOCONNECT)
  718.         IF (hst:=Gethostbyaddr(address, SIZEOF in_addr, AF_INET)) = NIL THEN Raise(ERR_NOCONNECT)
  719.     ELSE
  720.         IF (hst:=Gethostbyname(host)) = NIL THEN Raise(ERR_NOCONNECT)
  721.         address:=hst.addr_list[0]
  722.     ENDIF
  723.  
  724.     sain.family:=AF_INET
  725.     sain.addr.addr:=address.addr
  726.     sain.port:=Val(port)+unit
  727.     IF (sock:=Socket(AF_INET, SOCK_DGRAM, 0)) = -1 THEN Raise(ERR_NOSOCK)
  728.     Sendto(sock, cmd, size, 0, sain, SIZEOF sockaddr_in)
  729.  
  730.     fd_zero(readfds)
  731.     fd_set(sock, readfds)
  732.  
  733.     -> Some commands take a long time to complete, so increase the timeout value
  734.     IF cmd.opcode = SCSI_SEND_DIAGNOSTIC
  735.         tv.sec:=19
  736.         tv.usec:=5
  737.     ELSEIF cmd.opcode = SCSI_CD_START_STOP_UNIT
  738.         tv.sec:=10
  739.         tv.usec:=5
  740.     ELSEIF cmd.opcode = SCSI_DA_START_STOP_UNIT
  741.         tv.sec:=10
  742.         tv.usec:=5
  743.     ELSE
  744.         tv.sec:=1
  745.         tv.usec:=5
  746.     ENDIF
  747.  
  748.     IF WaitSelect(sock+1, readfds, NIL, NIL, tv, 0) > 0
  749.         IF fd_isset(sock, readfds)
  750.             IF ((received:=Recvfrom(sock, buffer, BUFFSIZE, 0, saou, SIZEOF sockaddr_in)) < 255)
  751.                 returncode:=Char(buffer)
  752.             ENDIF
  753.         ELSE
  754.             Raise(ERR_NOCONNECT)
  755.         ENDIF
  756.     ELSE
  757.         Raise(ERR_NOCONNECT)
  758.     ENDIF
  759.  
  760.     EXCEPT DO
  761.         IF sock <> -1 THEN CloseSocket(sock)
  762.         IF (socketbase) THEN CloseLibrary(socketbase)
  763.         SELECT exception
  764.             CASE ERR_NOBSD
  765.                 outlist('\ebError:\en', 'Unable to open bsdsocket.library')
  766.             CASE ERR_NOSOCK
  767.                 outlist('\ebError:\en', 'Unable to create socket')
  768.             CASE ERR_NOCONNECT
  769.                 outlist_d('<no device> (or unable to connect)', device, unit)
  770.         ENDSELECT
  771.  
  772. ENDPROC returncode, exception
  773.  
  774.  
  775. /*
  776. ** This procedure handles the data returned from an inquiry command, requesting
  777. ** vital page $80 (product serial number). It includes a limited amount of
  778. ** fallback as some buggy devices return the wrong page.
  779. */
  780. PROC process_serial(reply:PTR TO r_serial)
  781. DEF serial[100]:STRING, i=0, str[255]:STRING
  782.  
  783.     outlist_h('\ebPage Code\en', reply.code, NIL)
  784.     outlist_i('\ebPage Length\en', reply.length, NIL)
  785.  
  786.     SELECT $FF OF reply.code
  787.         CASE $0
  788.             FOR i:=0 TO (reply.length-1)
  789.             outlist_h('\ebKnown Page:\en', Char(reply+4+i), NIL)
  790.             ENDFOR
  791.         CASE $1 TO $7F
  792.             outlist_i('\ebASCII Length:\en', Char(reply+4), NIL)
  793.             StrCopy(str, (reply+5), Char(reply+4))
  794.             outlist('\ebText:\en', str)
  795.         CASE $80
  796.             StrCopy(serial, (reply+4), reply.length)
  797.             outlist('\ebSerial Number:\en', serial)
  798.         CASE $81
  799.             outlist('\ebOperating Definitions:\en', ' ')
  800.         CASE $82
  801.             outlist('\ebASCII Operating Definition:\en', ' ')
  802.         CASE $83 TO $EF
  803.             outlist('\ebVendor Specific Page:\en', ' ')
  804.         DEFAULT
  805.             outlist('\ebUnknown Page:\en', ' ')
  806.     ENDSELECT
  807. ENDPROC
  808.  
  809.  
  810. /*
  811. ** This procedure handles the data returned from an inquiry command. It has
  812. ** three modes of operation depending on the value of aflag. These are full
  813. ** (for full inquiry), minimum (for probes) and silent for passing the device
  814. ** type to the mode sense handler
  815. */
  816. PROC process_inquiry(device:PTR TO CHAR, unit, reply:PTR TO inquiry, aflg)
  817. DEF devtypestr[40]:STRING, buildstr[99]:STRING, vendor[8]:STRING,
  818.     product[16]:STRING, revision[4]:STRING, devtype=0
  819.  
  820.     devtype:=(reply.peripheral AND %00011111)
  821.     global_devtype:=devtype
  822.  
  823.     SELECT devtype
  824.         CASE DEV_DIRECT
  825.             StrCopy(devtypestr, 'DIRECT ACCESS (eg Disk)')
  826.         CASE DEV_SEQUENTIAL
  827.             StrCopy(devtypestr, 'SEQUENTIAL ACCESS (eg Tape)')
  828.         CASE DEV_PRINTER
  829.             StrCopy(devtypestr, 'PRINTER')
  830.         CASE DEV_PROCESSOR
  831.             StrCopy(devtypestr, 'PROCESSOR')
  832.         CASE DEV_WRITEONCE
  833.             StrCopy(devtypestr, 'WRITE-ONCE (eg Optical Disc)')
  834.         CASE DEV_CDROM
  835.             StrCopy(devtypestr, 'CD-ROM')
  836.         CASE DEV_SCANNER
  837.             StrCopy(devtypestr, 'SCANNER')
  838.         CASE DEV_OPTICAL
  839.             StrCopy(devtypestr, 'OPTICAL MEMORY')
  840.         CASE DEV_CHANGER
  841.             StrCopy(devtypestr, 'MEDIUM CHANGER (eg Jukebox)')
  842.         CASE DEV_COMMS
  843.             StrCopy(devtypestr, 'COMMUNICATIONS')
  844.         DEFAULT
  845.             StrCopy(devtypestr, 'UNKNOWN')
  846.     ENDSELECT
  847.  
  848.     MidStr(vendor, reply, 8, 7)
  849.     MidStr(product, reply, 16, 16)
  850.     MidStr(revision, reply, 32, 4)
  851.  
  852.     IF aflg=AFLG_INQUIRY_PROBE
  853.         StringF(buildstr, '\s \s \s :\s', vendor, product, revision, devtypestr)
  854.         outlist_d(buildstr, device, unit)
  855.     ELSEIF aflg=AFLG_INQUIRY_VERBOSE
  856.         outlist('\ebDriver:\en', device)
  857.         outlist_i('\ebUnit:\en', unit, NIL)
  858.         outlist('\ebVendor:\en', vendor)
  859.         outlist('\ebProduct:\en', product)
  860.         outlist('\ebRevision:\en', revision)
  861.         outlist('\ebType:\en', devtypestr)
  862.         IF (reply.rmb AND %10000000) = 128 THEN outlist('\ebRemovable Media:\en:', 'Yes') ELSE outlist('\ebRemovable Media:\en:', 'No')
  863.         outlist_i('\ebVendor Type Modifier:\en', (reply.rmb AND %01111111), NIL)
  864.         outlist_i('\ebISO Version:\en', (reply.versions AND %11000000), NIL)
  865.         outlist_i('\ebECMA Version:\en', (reply.versions AND %00111000), NIL )
  866.         outlist_i('\ebANSI Version:\en', (reply.versions AND %00000111), ' (SCSI Version)')
  867.         IF (reply.aenc AND %10000000) = 128 THEN outlist('\ebAENC Support:\en', 'Yes') ELSE outlist('\ebAENC Support:\en', 'No')
  868.         IF (reply.aenc AND %01000000) = 64 THEN outlist('\ebTrmIOP Support:\en', 'Yes') ELSE outlist('\ebTrmIOP Support:\en', 'No')
  869.         IF (reply.width AND %10000000) = 128 THEN outlist('\ebRelative Addressing:\en', 'Yes') ELSE outlist('\ebRelative Addressing:\en', 'No')
  870.         IF (reply.width AND %01000000) = 64 THEN outlist('\eb32bit Support:\en', 'Yes') ELSE outlist('\eb32bit Support:\en', 'No')
  871.         IF (reply.width  AND %00100000) = 32 THEN outlist('\eb16bit Support\en', 'Yes') ELSE outlist('\eb16bit Support\en', 'No')
  872.         outlist('\eb8bit Support\en', 'Yes')
  873.         IF (reply.width AND %00010000) = 16 THEN outlist('\ebSynchronous Support:\en', 'Yes') ELSE outlist('\ebSynchronous Support:\en', 'No')
  874.         IF (reply.width AND %00001000) = 8 THEN outlist('\ebLinked Support:\en', 'Yes') ELSE outlist('\ebLinked Support:\en', 'No')
  875.         IF (reply.width AND %00000010) = 2 THEN outlist('\ebCommand Queuing Support:\en', 'Yes') ELSE outlist('\ebCommand Queuing Support:\en', 'No')
  876.         IF (reply.width AND %00000001) = 1 THEN outlist('\ebSupported Reset Type:\en', 'Soft') ELSE outlist('\ebSupported Reset Type:\en', 'Hard')
  877.     ENDIF
  878. ENDPROC
  879.  
  880.  
  881. /*
  882. ** This procedure handles the data returned from a capacity query
  883. */
  884. PROC process_capacity(reply:PTR TO capacity)
  885. DEF buildstr[99]:STRING, tcap, vcap
  886.  
  887.     tcap:=Div(Mul(Div(reply.blocks, 1024), reply.bsize), 1024)
  888.     vcap:=Div(Mul(Div(reply.blocks, 1000), reply.bsize), 1000)
  889.  
  890.     outlist_i('\ebLast Block:\en', reply.blocks, NIL)
  891.     outlist_i('\ebBlock Size:\en', reply.bsize, ' bytes')
  892.  
  893.     ->Calculations may seem really weird and convoluted, but its to try and avoid
  894.     ->floating point maths and rounding errors
  895.     IF tcap<1024 THEN StringF(buildstr, '~ \dMB', tcap) ELSE StringF(buildstr, '~ \d.\d GB  (\d MB)', Div(tcap, 1024), (Mod((tcap*10), 10240)/1024), tcap)
  896.     outlist('\ebTrue Capacity:\en', buildstr)
  897.     IF vcap<1000 THEN StringF(buildstr, '~ \dmb', vcap) ELSE StringF(buildstr, '~ \d.\d gb  (\d mb)', Div(vcap, 1000), (Mod(vcap, 1000)/100), vcap)
  898.     outlist('\ebVendor Capacity:\en', buildstr)
  899.  
  900. ENDPROC
  901.  
  902.  
  903. /*
  904. ** This procedure handles the data returned from a Read Table of Contents
  905. ** query
  906. */
  907. PROC process_toc(reply:PTR TO toc)
  908. DEF track:PTR TO toc_d, i
  909.  
  910.     outlist_i('\ebStarting Track:\eb', reply.firsttrack, NIL)
  911.     outlist_i('\ebLast Track:\eb', reply.lasttrack, NIL)
  912.  
  913.     track:=reply + SIZEOF toc
  914.  
  915.     FOR i:=reply.firsttrack TO reply.lasttrack
  916.         outlist(' ', ' ')
  917.         outlist_i('\ebTrack Number:\en', track.track, NIL)
  918.         IF (track.adr_ctrl AND %00000100)=0
  919.             outlist('\ebType:\en', 'AUDIO')
  920.             IF (track.adr_ctrl AND %00001000)=0 THEN outlist('\ebAudio Channels:\en', '2') ELSE outlist('\ebAudio Channels:\en', '4')
  921.             IF (track.adr_ctrl AND %00000001)=0 THEN outlist('\ebEmphasis:\en', 'Audio IS pre-emphasised') ELSE outlist('\ebEmphasis:\en', 'Audio NOT pre-emphasised')
  922.         ELSE
  923.             outlist('\ebTrack Type:\en', 'DATA')
  924.         ENDIF
  925.         IF (track.adr_ctrl AND %00000010)=0 THEN outlist('\ebCopyright:\en', 'Digital Copy Prohibited') ELSE outlist('\ebCopyright:\en', 'Digital Copy Permitted')
  926.         track:=track + SIZEOF toc_d
  927.     ENDFOR
  928.  
  929. ENDPROC
  930.  
  931. PROC process_atip(reply:PTR TO r_atip)
  932.     outlist_i('\ebATIP Data Length:\en', reply.atiplen, NIL)
  933.     outlist_i('\ebIndicitive Writing Power:\en', (reply.itwp AND %11110000), NIL)
  934.     outlist_i('\ebReference Speed:\en', (Char(reply+4) AND %00000111), NIL)
  935.     IF (reply.disctype AND %01000000) = 64 THEN outlist('\ebDisc Type:\en', 'CD-RW') ELSE outlist('\ebDisc Type:\en', 'CD-R')
  936.     outlist_i('\ebATIP Start Time of Lead-In',reply.startmin, ' minutes')
  937.     outlist_i('\ebATIP Start Time of Lead-In',reply.startsec, ' seconds')
  938.     outlist_i('\ebATIP Start Time of Lead-In',reply.startframe, ' frames')
  939.     outlist_i('\ebATIP Start Time of Lead-Out',reply.endmin, ' minutes')
  940.     outlist_i('\ebATIP Start Time of Lead-Out',reply.endsec, ' seconds')
  941.     outlist_i('\ebATIP Start Time of Lead-Out',reply.endframe, ' frames')
  942. ENDPROC
  943.  
  944. /*
  945. ** This procedure handles the data returned from a request sense key query
  946. */
  947. PROC process_sense(reply:PTR TO r_sense)
  948.  
  949.     SELECT $F OF (reply.sensekey AND %00001111)
  950.         CASE $0
  951.             outlist_h('\ebSense Key:\en', 0, ' : No Specific Sense Key Info Available')
  952.         CASE $1
  953.             outlist_h('\ebSense Key:\en', 1, ' : Command recovered successfully from error')
  954.         CASE $2
  955.             outlist_h('\ebSense Key:\en', 2, ' : Unit is not ready for commands')
  956.         CASE $3
  957.             outlist_h('\ebSense Key:\en', 3, ' : Medium Error. The medium may contain errors or defects.')
  958.         CASE $4
  959.             outlist_h('\ebSense Key:\en', 4, ' : DEVICE REPORTED HARDWARE FAILURE!!!')
  960.         CASE $5
  961.             outlist_h('\ebSense Key:\en', 5, ' : This device does not support that command')
  962.         CASE $6
  963.             outlist_h('\ebSense Key:\en', 6, ' : Unit Attention, possible media change in progress')
  964.         CASE $7
  965.             outlist_h('\ebSense Key:\en', 7, ' : Medium is write-protected')
  966.         CASE $8
  967.             outlist_h('\ebSense Key:\en', 8, ' : Attempt to read unformatted medium')
  968.         CASE $9
  969.             outlist_h('\ebSense Key:\en', 9, ' : Vendor specific sense key')
  970.         CASE $A
  971.             outlist_h('\ebSense Key:\en', 10, ' : Copy/Compare command aborted due to read/write error')
  972.         CASE $B
  973.             outlist_h('\ebSense Key:\en', 11, ' : Command was aborted by the device')
  974.         CASE $C
  975.             outlist_h('\ebSense Key:\en', 12, ' : Equal comparison satisfied')
  976.         CASE $D
  977.             outlist_h('\ebSense Key:\en', 13, ' : Volume Overflow')
  978.         CASE $E
  979.             outlist_h('\ebSense Key:\en', 14, ' : Miscompare')
  980.         DEFAULT
  981.             outlist_h('\ebSense Key:\en', 15, ' : Reserved Sense Key')
  982.     ENDSELECT
  983.  
  984.     IF reply.sensecode > NIL
  985.         outlist_h('\ebAdditional Sense Code:\en', reply.sensecode, NIL)
  986.         outlist_h('\ebSense Code Qualifier:\en', reply.sensequal, NIL)
  987.     ENDIF
  988.  
  989. ENDPROC
  990.  
  991.  
  992. /*
  993. ** This procedure handles the data returned from a mode sense request
  994. ** (ie Device Parameters). It is quite complex because the data is in the form
  995. ** of many pages which have to be processed. In addition to that, a page type
  996. ** may have to be processed differently, or have a different meaning depending
  997. ** on the type of device queried. It's the master procedure for mode sense data
  998. ** and farms off the actual decoding to the specific page type handlers.
  999. */
  1000. PROC process_modesense(reply:PTR TO m_sense6, modesize)
  1001. DEF page:PTR TO CHAR, pagetype, reply2:PTR TO m_sense10, ptr:PTR TO CHAR,
  1002. datalen -> fh, out[100]:STRING
  1003.  
  1004.     IF modesize=10
  1005.         reply2:=reply
  1006.         outlist_i('\ebMode Data Length:\en', reply2.datalen, ' bytes')
  1007.         IF reply2.medium = 0 THEN outlist('\ebInserted Medium Type:\en','Default') ELSE outlist_i('\ebInserted Medium Type:\en', reply2.medium, ' (See supported media page)')
  1008.         outlist_i('\ebDevice Specific Parameter:\en', reply2.devpar, NIL)
  1009.         outlist_i('\ebDescriptor Length:\en', reply2.desclen, ' bytes')
  1010.         outlist_i('\ebDensity Code:\en', (Shr(reply2.blocks, 24) AND 255), NIL)
  1011.         outlist_i('\ebNumber of Blocks:\en', (reply2.blocks AND $00FFFFFF),NIL)
  1012.         outlist_i('\ebBlock Length:\en', (reply2.blocklen AND $00FFFFFF), ' bytes')
  1013.         datalen:=reply2.datalen
  1014.         IF reply2.desclen = 8 THEN page:=(reply2 + SIZEOF m_sense10) ELSE page:=(reply + 8)
  1015.     ELSE
  1016.         outlist_i('\ebMode Data Length:\en', reply.datalen, ' bytes')
  1017.         IF reply.medium = 0 THEN outlist('\ebInserted Medium Type:\en', 'Default') ELSE outlist_i('\ebInserted Medium Type:\en', reply.medium, ' (See supported media page)')
  1018.         outlist_i('\ebDevice Specific Parameter:\en', reply.devpar, NIL)
  1019.         outlist_i('\ebDescriptor Length:\en', reply.desclen, ' bytes')
  1020.         outlist_i('\ebDensity Code:\en', (Shr(reply.blocks, 24) AND 255), NIL)
  1021.         outlist_i('\ebNumber of Blocks:\en', (reply.blocks AND $00FFFFFF),NIL)
  1022.         outlist_i('\ebBlock Length:\en', (reply.blocklen AND $00FFFFFF), ' bytes')
  1023.         datalen:=reply.datalen
  1024.         IF reply.desclen = 8 THEN page:=(reply + SIZEOF m_sense6) ELSE page:=(reply + 4)
  1025.     ENDIF
  1026.         ptr:=reply
  1027.         WHILE page < (ptr + datalen)
  1028.             pagetype:=(Char(page) AND %00111111)
  1029.             outlist(' ', ' ')
  1030.             SELECT pagetype
  1031.                 CASE $1
  1032.                     process_modesense_1(page)
  1033.                 CASE $2
  1034.                     process_modesense_2(page)
  1035.                 CASE $3
  1036.                     process_modesense_3(page)
  1037.                 CASE $4
  1038.                     process_modesense_4(page)
  1039.                 CASE $5
  1040.                     process_modesense_5(page)
  1041.                 CASE $7
  1042.                     process_modesense_7(page)
  1043.                 CASE $8
  1044.                     process_modesense_8(page)
  1045.                 CASE $9
  1046.                     process_modesense_9(page)
  1047.                 CASE $A
  1048.                     process_modesense_A(page)
  1049.                 CASE $B
  1050.                     process_modesense_B(page)
  1051.                 CASE $C
  1052.                     process_modesense_C(page)
  1053.                 CASE $D
  1054.                     process_modesense_D(page)
  1055.                 CASE $E
  1056.                     process_modesense_E(page)
  1057.                 CASE $F
  1058.                     process_modesense_F(page)
  1059.                 CASE $10
  1060.                     process_modesense_10(page)
  1061.                 CASE $11
  1062.                     process_modesense_11(page)
  1063.                 CASE $12
  1064.                     process_modesense_12(page)
  1065.                 CASE $13
  1066.                     process_modesense_13(page)
  1067.                 CASE $14
  1068.                     process_modesense_14(page)
  1069.                 CASE $18
  1070.                     process_modesense_18(page)
  1071.                 CASE $19
  1072.                     process_modesense_19(page)
  1073.                 CASE $1A
  1074.                     process_modesense_1A(page)
  1075.                 CASE $1C
  1076.                     process_modesense_1C(page)
  1077.                 CASE $2A
  1078.                     process_modesense_2A(page)
  1079.                 CASE $21
  1080.                     process_modesense_21(page)
  1081.                 CASE $39
  1082.                     process_modesense_39(page)
  1083.                 DEFAULT
  1084.                     outlist('\ebInformation Page:\en', 'Vendor Specific')
  1085.                     outlist_i('\ebPage Code:\en', pagetype , NIL)
  1086.                     outlist_i('\ebPage Length:\en', Char(page+1), ' bytes')
  1087.             ENDSELECT
  1088.             
  1089.         /* uncomment this section to dump page codes to RAM */
  1090.         /*
  1091.         StringF(out, 'RAM:pagecode.\d', pagetype)
  1092.         fh:=Open(out, MODE_NEWFILE)
  1093.         Write(fh, page, Char(page+1))
  1094.         Close(fh)
  1095.         */
  1096.  
  1097.         page:=(page + Char(page+1) +2)
  1098.  
  1099.         ENDWHILE
  1100. ENDPROC
  1101.  
  1102.  
  1103. /*
  1104. ** Handler for a specific mode page
  1105. */
  1106. PROC process_modesense_1(page)
  1107.  
  1108.     SELECT $A OF global_devtype
  1109.         CASE DEV_DIRECT
  1110.             outlist('\ebInformation Page:\en', 'Error Recovery Parameters')
  1111.             outlist('\ebPage Code:\en', '1')
  1112.             outlist_i('\ebPage Length:\en', Char(page+1), ' bytes')
  1113.             IF (Char(page+2) AND %10000000) = 128 THEN outlist('\ebAutomatic Write Reallocation:\en', 'Yes') ELSE  outlist('\ebAutomatic Write Reallocation:\en', 'No')
  1114.             IF (Char(page+2) AND %01000000) = 64 THEN outlist('\ebAutomatic Read Reallocation:\en', 'Yes') ELSE outlist('\ebAutomatic Read Reallocation:\en', 'No')
  1115.             IF (Char(page+2) AND %00100000) = 32 THEN outlist('\ebTB:\en', 'Yes') ELSE outlist('\ebTB:\en', 'No')
  1116.             IF (Char(page+2) AND %00010000) = 16 THEN outlist('\ebRC:\en', 'Yes') ELSE outlist('\ebRC:\en', 'No')
  1117.             IF (Char(page+2) AND %00001000) = 8 THEN outlist('\ebEER:\en', 'Yes') ELSE outlist('\ebEER:\en', 'No')
  1118.             IF (Char(page+2) AND %00000100) = 4 THEN outlist('\ebPER:\en', 'Yes') ELSE outlist('\ebPER:\en', 'No')
  1119.             IF (Char(page+2) AND %00000010) = 2 THEN outlist('\ebDTE:\en', 'Yes') ELSE outlist('\ebDTE:\en', 'No')
  1120.             IF (Char(page+2) AND %00000001) = 1 THEN outlist('\ebDCR:\en', 'Yes') ELSE outlist('\ebDCR:\en', 'No')
  1121.             outlist_i('\ebRetries on Read Error:\en', Char(page+3), NIL)
  1122.             outlist_i('\ebRetries on Write Error:\en', Char(page+8), NIL)
  1123.             outlist_i('\ebCorrection Span:\en', Char(page+4), ' bits')
  1124.             outlist_i('\ebHead Offset Count:\en', Char(page+5), NIL)
  1125.             outlist_i('\ebData Strobe Offset Count:\en', Char(page+6), NIL)
  1126.             outlist_i('\ebRecovery Time Limit:\en', Int(page+10), ' Ms')
  1127.         CASE DEV_SEQUENTIAL
  1128.             outlist('\ebInformation Page:\en', 'Error Recovery Parameters')
  1129.             outlist('\ebPage Code:\en', '1')
  1130.             outlist_i('\ebPage Length:\en', Char(page+1), NIL)
  1131.             outlist_i('\ebRetries on Read Error:\en', Char(page+3), NIL)
  1132.             outlist_i('\ebRetries on Write Error:\en', Char(page+8), NIL)
  1133.         CASE DEV_CDROM
  1134.             outlist('\ebInformation Page:\en', 'Error Recovery Parameters')
  1135.             outlist('\ebPage Code:\en', '1')
  1136.             outlist_i('\ebPage Length:\en', Char(page+1), NIL)
  1137.             outlist_i('\ebError Recovery Parameter:\en', Char(page+2), NIL)
  1138.             outlist_i('\ebRetries on Read Error:\en', Char(page+3), NIL)
  1139.         DEFAULT
  1140.             outlist('\ebInformation Page:\en', 'Unsupported or Reserved for this device class')
  1141.             outlist('\ebPage Code:\en', '1')
  1142.     ENDSELECT
  1143.  
  1144. ENDPROC
  1145.  
  1146.  
  1147. /*
  1148. ** Handler for a specific mode page
  1149. */
  1150. PROC process_modesense_2(page)
  1151.  
  1152.     outlist('\ebInformation Page:\en', 'Disconnection and Reconnection Parameters')
  1153.     outlist('\ebPage Code:\en', '2')
  1154.     outlist_i('\ebPage Length:\en', Char(page+1), ' bytes')
  1155.     outlist_i('\ebBuffer Full Ratio:\en', Char(page+2), NIL)
  1156.     outlist_i('\ebBuffer Empty Ratio:\en', Char(page+3), NIL)
  1157.     outlist_i('\ebBus Inactivity Limit:\en', Int(page+4), ' *100 us')
  1158.     outlist_i('\ebDisconnect Time Limit:\en', Int(page+6), ' *100 us')
  1159.     outlist_i('\ebConnect Time Limit:\en', Int(page+8), ' *100 us')
  1160.     outlist_i('\ebMaximum Burst Size:\en', Int(page+10), ' *512 bytes')
  1161.  
  1162. ENDPROC
  1163.  
  1164.  
  1165. /*
  1166. ** Handler for a specific mode page
  1167. */
  1168. PROC process_modesense_3(page)
  1169.  
  1170.     IF global_devtype=DEV_DIRECT
  1171.         outlist('\ebInformation Page:\en', 'Formatting Parameters')
  1172.         outlist('\ebPage Code:\en', '3')
  1173.         outlist_i('\ebPage Length:\en', Char(page+1), ' bytes')
  1174.         outlist_i('\ebTracks Per Zone:\en', Int(page+2), NIL)
  1175.         outlist_i('\ebAlt. Sectors Per Zone:\en', Int(page+4), NIL)
  1176.         outlist_i('\ebAlt. Tracks Per Zone:\en', Int(page+6), NIL)
  1177.         outlist_i('\ebAlt. Tracks Per Logical Unit:\en', Int(page+8), NIL)
  1178.         outlist_i('\ebSectors Per Track:\en', Int(page+10), NIL)
  1179.         outlist_i('\ebBytes Per Physical Sector:\en', Int(page+12), NIL)
  1180.         outlist_i('\ebInterleave:\en', Int(page+14), NIL)
  1181.         outlist_i('\ebTrack Skew Factor:\en', Int(page+16), NIL)
  1182.         outlist_i('\ebCylinder Skew Factor:\en', Int(page+18), NIL)
  1183.     ELSE
  1184.         outlist('\ebInformation Page:\en', 'Unsupported or Reserved for this device class')
  1185.         outlist('\ebPage Code:\en', '3')
  1186.     ENDIF
  1187.  
  1188. ENDPROC
  1189.  
  1190.  
  1191. /*
  1192. ** Handler for a specific mode page
  1193. */
  1194. PROC process_modesense_4(page)
  1195.  
  1196.     IF global_devtype=DEV_DIRECT
  1197.         outlist('\ebInformation Page:\en', 'Rigid Disk Geometry Parameters')
  1198.         outlist('\ebPage Code:\en', '4')
  1199.         outlist_i('\ebPage Length:\en', Char(page+1), ' bytes')
  1200.         outlist_i('\ebCylinders:\en', And(Long(page+1), $00FFFFFF) , NIL)
  1201.         outlist_i('\ebHeads:\en', Char(page+5), NIL)
  1202.         outlist_i('\ebStart Write PreComp:\en', And(Long(page+5), $00FFFFFF), NIL)
  1203.         outlist_i('\ebStart Reduced Write:\en', And(Long(page+8), $00FFFFFF), NIL)
  1204.         IF (Int(page+12) = 0) THEN outlist('\ebStep Rate\en:', 'Device Default') ELSE outlist_i('\ebStep Rate:\en', Int(page+12), ' *100 ns')
  1205.         outlist_i('\ebLanding Cylinder:\en', And(Long(page+13), $00FFFFFF), NIL)
  1206.         outlist_i('\ebRotational Offset:\en', Char(page+18), NIL)
  1207.         outlist_i('\ebRotation Rate:', Int(page+20), ' rpm')
  1208.     ELSE
  1209.         outlist('\ebInformation Page:\en', 'Unsupported or Reserved for this device class')
  1210.         outlist('\ebPage Code:\en', '4')
  1211.     ENDIF
  1212.  
  1213. ENDPROC
  1214.  
  1215.  
  1216. /*
  1217. ** Handler for a specific mode page
  1218. */
  1219. PROC process_modesense_5(page)
  1220.  
  1221.     IF global_devtype=DEV_DIRECT
  1222.         outlist('\ebInformation Page:\en', 'Flexible Disk Geometry Parameters')
  1223.         outlist('\ebPage Code:\en', '5')
  1224.         outlist_i('\ebPage Length:\en', Char(page+1), ' bytes')
  1225.         outlist_i('\ebTransfer Rate\en', (Int(page+2)/8), ' K/sec')
  1226.         outlist_i('\ebHeads\en:', Char(page+4), NIL)
  1227.         outlist_i('\ebSectors Per Track:\en', Char(page+5), NIL)
  1228.         outlist_i('\ebBytes Per Sector:\en', Int(page+6), NIL)
  1229.         outlist_i('\ebCylinders:\en', Int(page+8), NIL)
  1230.         IF Int(page+14) = 0 THEN outlist('\ebStep Rate\en:', 'Device Default') ELSE outlist_i('\ebStep Rate:\en', Int(page+14), ' *100 us')
  1231.         outlist_i('\ebRotation Rate:\en', Int(page+28), ' rpm')
  1232.     ELSE
  1233.         outlist('\ebInformation Page:\en', 'Unsupported or Reserved for this device class')
  1234.         outlist('\ebPage Code:\en', '5')
  1235.     ENDIF
  1236.  
  1237. ENDPROC
  1238.  
  1239.  
  1240. /*
  1241. ** Handler for a specific mode page
  1242. */
  1243. PROC process_modesense_7(page)
  1244.  
  1245.     SELECT $A OF global_devtype
  1246.         CASE DEV_DIRECT
  1247.             outlist('\ebInformation Page:\en', 'Verify Error Recovery Parameters')
  1248.             outlist('\ebPage Code:\en', '7')
  1249.             outlist_i('\ebPage Length:\en', Char(page+1), ' bytes')
  1250.             IF (Char(page+2) AND %00001000) = 8 THEN outlist('\ebEER:\en', 'Yes') ELSE outlist('\ebEER:\en', 'No')
  1251.             IF (Char(page+2) AND %00000100) = 4 THEN outlist('\ebPER:\en', 'Yes') ELSE outlist('\ebPER:\en', 'No')
  1252.             IF (Char(page+2) AND %00000010) = 2 THEN outlist('\ebDTE:\en', 'Yes') ELSE outlist('\ebDTE:\en', 'No')
  1253.             IF (Char(page+2) AND %00000001) = 1 THEN outlist('\ebDCR:\en', 'Yes') ELSE outlist('\ebDCR:\en', 'No')
  1254.             outlist_i('\ebVerify Retries:\en', Char(page+3), NIL)
  1255.             outlist_i('\ebVerify Correction Span:\en', Char(page+4), ' bits')
  1256.             outlist_i('\ebVerify Recovery Time Limit:\en', Int(page+10), ' Ms')
  1257.         CASE DEV_CDROM
  1258.             outlist('\ebInformation Page:\en', 'Verify Error Recovery Parameters')
  1259.             outlist('\ebPage Code:\en', '7')
  1260.             outlist_i('\ebPage Length:\en', Char(page+1), ' bytes')
  1261.             outlist_h('\ebError Recovery Parameter:\en', Char(page+2), NIL)
  1262.             outlist_i('\ebVerify Retries:\en', Char(page+3), NIL)
  1263.         DEFAULT
  1264.             outlist('\ebInformation Page:\en', 'Unsupported or Reserved for this device class')
  1265.             outlist('\ebPage Code:\en', '7')
  1266.     ENDSELECT
  1267.  
  1268. ENDPROC
  1269.  
  1270.  
  1271. /*
  1272. ** Handler for a specific mode page
  1273. */
  1274. PROC process_modesense_8(page)
  1275.  
  1276.     SELECT $A OF global_devtype
  1277.         CASE DEV_DIRECT, DEV_CDROM, DEV_OPTICAL
  1278.         outlist('\ebInformation Page:\en', 'Cache Parameters')
  1279.         outlist('\ebPage Code:\en', '8')
  1280.         outlist_i('\ebPage Length:\en', Char(page+1), ' bytes')
  1281.         IF (Char(page+2) AND %00000001) = 0 THEN outlist('\ebRead Cache:\en', 'Enabled') ELSE outlist('\ebRead Cache:\en', 'Disabled or Unavailable')
  1282.         IF (Char(page+2) AND %00000100) = 4 THEN outlist('\ebWrite Cache:\en', 'Enabled') ELSE outlist('\ebWrite Cache:\en', 'Disabled or Unavailable')
  1283.         outlist_i('\ebMin Pre-Fetch:\en', Int(page+6), ' bytes')
  1284.         outlist_i('\ebMax Pre-Fetch:\en', Int(page+8), ' bytes')
  1285.     DEFAULT
  1286.         outlist('\ebInformation Page:\en', 'Unsupported or Reserved for this device class')
  1287.         outlist('\ebPage Code:\en', '8')
  1288.     ENDSELECT
  1289.  
  1290. ENDPROC
  1291.  
  1292.  
  1293. /*
  1294. ** Handler for a specific mode page
  1295. */
  1296. PROC process_modesense_9(page)
  1297.  
  1298.     outlist('\ebInformation Page:\en', 'Interface Mode')
  1299.     outlist('\ebPage Code:\en', '9')
  1300.     outlist_i('\ebPage Length:\en', Char(page+1), ' bytes')
  1301.     IF (Int(page+2)) = 0
  1302.         outlist('\ebInterface ID:\en', 'Small Computer Systems Interface (SCSI)')
  1303.     ELSEIF (Int(page+2))=1
  1304.         outlist('\ebInterface ID:\en', 'Storage Module Interface (SMI)')
  1305.     ELSEIF (Int(page+2))=2
  1306.         outlist('\ebInterface ID:\en', 'Enhanced Small Device Interface (ESDI)')
  1307.     ELSEIF (Int(page+2))=3
  1308.         outlist('\ebInterface ID:\en', 'Intelligent Peripheral Interface 2 (IPI-2)')
  1309.     ELSEIF (Int(page+2))=4
  1310.         outlist('\ebInterface ID:\en', 'Intelligent Peripheral Interface 3 (IPI-3)')
  1311.     ELSE
  1312.         outlist('\ebInterface ID:\en', 'Vendor Specific')
  1313.     ENDIF
  1314.  
  1315. ENDPROC
  1316.  
  1317.  
  1318. /*
  1319. ** Handler for a specific mode page
  1320. */
  1321. PROC process_modesense_A(page)
  1322.  
  1323.     outlist('\ebInformation Page:\en', 'Control Mode')
  1324.     outlist('\ebPage Code:\en', '10 ($A)')
  1325.     outlist_i('\ebPage Length:\en', Char(page+1), ' bytes')
  1326.     IF (Char(page+2) AND %00000001)=1 THEN outlist('\ebReport Log Exceptions:\en', 'Yes') ELSE outlist('\ebReport Log Exceptions:\en', 'No')
  1327.     IF (Char(page+3) AND %11110000)=16
  1328.         outlist('\ebQueuing Algorithm:\en', 'Unrestricted reordering allowed')
  1329.     ELSEIF (Char(page+3) AND %11110000)=0
  1330.         outlist('\ebQueuing Algorithm:\en', 'Restricted reordering')
  1331.     ELSE
  1332.         outlist('\ebQueuing Algorithm:\en', 'Vendor Specific')
  1333.     ENDIF
  1334.     IF (Char(page+3) AND %00000001)=1 THEN outlist('\ebQueuing:', 'Disabled') ELSE outlist('\ebQueuing:', 'Enabled')
  1335.     IF (Char(page+4) AND %10000000) = 128 THEN outlist('\ebExtended Contingent Allegiance:\en:', 'Enabled') ELSE outlist('\ebExtended Contingent Allegiance:\en:', 'Disabled')
  1336.     outlist_i('\ebAEN Holdoff Period:\en', Int(page+6), NIL)
  1337.  
  1338. ENDPROC
  1339.  
  1340.  
  1341. /*
  1342. ** Handler for a specific mode page
  1343. */
  1344. PROC process_modesense_B(page)
  1345.  
  1346.     SELECT $A OF global_devtype
  1347.         CASE DEV_DIRECT
  1348.             outlist('\ebInformation Page:\en', 'Supported Media')
  1349.             outlist('\ebPage Code:\en', '11 ($B)')
  1350.             outlist_i('\ebPage Length:\en', Char(page+1), ' bytes')
  1351.             outlist_i('\ebMedium Type 1:\en', Char(page+4), NIL)
  1352.             outlist_i('\ebMedium Type 2:\en', Char(page+5), NIL)
  1353.             outlist_i('\ebMedium Type 3:\en', Char(page+6), NIL)
  1354.             outlist_i('\ebMedium Type 4:\en', Char(page+7), NIL)
  1355.         CASE DEV_CDROM
  1356.             outlist('\ebInformation Page:\en', 'Supported Media')
  1357.             outlist('\ebPage Code:\en', '11 ($B)')
  1358.             outlist_i('\ebPage Length:\en', Char(page+1), ' bytes')
  1359.  
  1360.             IF Char(page+4) = NIL
  1361.                 outlist('\ebMedium Type 1:\en', 'Only the Default medium')
  1362.             ELSEIF Char(page+4) = 1
  1363.                 outlist('\ebMedium Type 1:\en', '120mm Data CD-ROM')
  1364.             ELSEIF Char(page+4) = 2
  1365.                 outlist('\ebMedium Type 1:\en', '120mm Audio CD-ROM')
  1366.             ELSEIF Char(page+4) = 3
  1367.                 outlist('\ebMedium Type 1:\en', '120mm Mixed Data & Audio')
  1368.             ELSEIF Char(page+4) = 5
  1369.                 outlist('\ebMedium Type 1:\en', '80mm Data CD-ROM')
  1370.             ELSEIF Char(page+4) = 6
  1371.                 outlist('\ebMedium Type 1:\en', '80mm Audio CD-ROM')
  1372.             ELSEIF Char(page+4) = 7
  1373.                 outlist('\ebMedium Type 1:\en', '80mm Mixed Data & Audio')
  1374.             ELSE
  1375.                 outlist('\ebMedium Type 1:\en', 'Vendor Specific')
  1376.             ENDIF
  1377.  
  1378.             IF Char(page+5) = NIL
  1379.                 outlist('\ebMedium Type 2:\en', 'Only the Default medium')
  1380.             ELSEIF Char(page+5) = 1
  1381.                 outlist('\ebMedium Type 2:\en', '120mm Data CD-ROM')
  1382.             ELSEIF Char(page+5) = 2
  1383.                 outlist('\ebMedium Type 2:\en', '120mm Audio CD-ROM')
  1384.             ELSEIF Char(page+5) = 3
  1385.                 outlist('\ebMedium Type 2:\en', '120mm Mixed Data & Audio')
  1386.             ELSEIF Char(page+5) = 5
  1387.                 outlist('\ebMedium Type 2:\en', '80mm Data CD-ROM')
  1388.             ELSEIF Char(page+5) = 6
  1389.                 outlist('\ebMedium Type 2:\en', '80mm Audio CD-ROM')
  1390.             ELSEIF Char(page+5) = 7
  1391.                 outlist('\ebMedium Type 2:\en', '80mm Mixed Data & Audio')
  1392.             ELSE
  1393.                 outlist('\ebMedium Type 2:\en', 'Vendor Specific')
  1394.             ENDIF
  1395.  
  1396.             IF Char(page+6) = NIL
  1397.                 outlist('\ebMedium Type 3:\en', 'Only the Default medium')
  1398.             ELSEIF Char(page+6) = 1
  1399.                 outlist('\ebMedium Type 3:\en', '120mm Data CD-ROM')
  1400.             ELSEIF Char(page+6) = 2
  1401.                 outlist('\ebMedium Type 3:\en', '120mm Audio CD-ROM')
  1402.             ELSEIF Char(page+6) = 3
  1403.                 outlist('\ebMedium Type 3:\en', '120mm Mixed Data & Audio')
  1404.             ELSEIF Char(page+6) = 5
  1405.                 outlist('\ebMedium Type 3:\en', '80mm Data CD-ROM')
  1406.             ELSEIF Char(page+6) = 6
  1407.                 outlist('\ebMedium Type 3:\en', '80mm Audio CD-ROM')
  1408.             ELSEIF Char(page+6) = 7
  1409.                 outlist('\ebMedium Type 3:\en', '80mm Mixed Data & Audio')
  1410.             ELSE
  1411.                 outlist('\ebMedium Type 3:\en', 'Vendor Specific')
  1412.             ENDIF
  1413.  
  1414.             IF Char(page+7) = NIL
  1415.                 outlist('\ebMedium Type 4:\en', 'Only the Default medium')
  1416.             ELSEIF Char(page+7) = 1
  1417.                 outlist('\ebMedium Type 4:\en', '120mm Data CD-ROM')
  1418.             ELSEIF Char(page+7) = 2
  1419.                 outlist('\ebMedium Type 4:\en', '120mm Audio CD-ROM')
  1420.             ELSEIF Char(page+7) = 3
  1421.                 outlist('\ebMedium Type 4:\en', '120mm Mixed Data & Audio')
  1422.             ELSEIF Char(page+7) = 5
  1423.                 outlist('\ebMedium Type 4:\en', '80mm Data CD-ROM')
  1424.             ELSEIF Char(page+7) = 6
  1425.                 outlist('\ebMedium Type 4:\en', '80mm Audio CD-ROM')
  1426.             ELSEIF Char(page+7) = 7
  1427.                 outlist('\ebMedium Type 4:\en', '80mm Mixed Data & Audio')
  1428.             ELSE
  1429.                 outlist('\ebMedium Type 4:\en', 'Vendor Specific')
  1430.             ENDIF
  1431.         DEFAULT
  1432.             outlist('\ebInformation Page:\en', 'Unsupported or Reserved for this device class')
  1433.             outlist('\ebPage Code:\en', '11 ($B)')
  1434.     ENDSELECT
  1435.  
  1436. ENDPROC
  1437.  
  1438.  
  1439. /*
  1440. ** Handler for a specific mode page
  1441. */
  1442. PROC process_modesense_C(page)
  1443.  
  1444.     IF global_devtype=DEV_DIRECT
  1445.         outlist('\ebInformation Page:\en', 'Notch Parameters')
  1446.         outlist('\ebPage Code:\en', '12 ($C)')
  1447.         outlist_i('\ebPage Length:\en', Char(page+1), ' bytes')
  1448.         IF (Char(page+2) AND %10000000)=128 THEN outlist('\ebNotched Drive:\en', 'Yes') ELSE outlist('\ebNotched Drive:\en', 'No')
  1449.         IF (Char(page+2) AND %01000000)=64 THEN outlist('\ebNotch Boundary Type:\en', 'Logical') ELSE outlist('\ebNotch Boundary Type:\en', 'Logical')
  1450.         outlist_i('\ebMaximum Notches:\en', Int(page+4), NIL)
  1451.         outlist_i('\ebActive Notch:\en', Int(page+6), NIL)
  1452.         outlist_i('\ebActive Notch Start:\en', Long(page+8), NIL)
  1453.         outlist_i('\ebActive Notch End:\en', Long(page+12), NIL)
  1454.         outlist_i('\ebPages Notched A:\en', Long(page+16), NIL)
  1455.         outlist_i('\ebPages Notched B:\en', Long(page+20), NIL)
  1456.     ELSE
  1457.         outlist('\ebInformation Page:\en', 'Unsupported or Reserved for this device class')
  1458.         outlist('\ebPage Code:\en', '12 ($C)')
  1459.     ENDIF
  1460.  
  1461. ENDPROC
  1462.  
  1463.  
  1464. /*
  1465. ** Handler for a specific mode page
  1466. */
  1467. PROC process_modesense_D(page)
  1468.  
  1469.     IF global_devtype=DEV_CDROM
  1470.         outlist('\ebInformation Page:\en', 'CD-ROM Parameters')
  1471.         outlist('\ebPage Code:\en', '13 ($D)')
  1472.         outlist_i('\ebPage Length:\en', Char(page+1), ' bytes')
  1473.         outlist_h('\ebInactivity Multiplier:\en', (Char(page+3) AND %00001111), NIL)
  1474.         outlist_i('\ebS Units per MSF:\en', Int(page+4), NIL)
  1475.         outlist_i('\ebF Units per MSF:\en', Int(page+6), NIL)
  1476.     ELSEIF global_devtype=DEV_DIRECT
  1477.         outlist('\ebVendor Information Page:\en', 'Power Condition')
  1478.         outlist('\ebCAUTION:\en', 'Vendor Specific Page Decoded')
  1479.         outlist('\ebREFERENCE:\en', 'Quantum Fireball ST 2.1/3.2/4.3/6.4 GB S')
  1480.         outlist('\ebPage Code:\en', '13 ($D)')
  1481.         outlist_i('\ebPage Length:\en', Char(page+1), ' bytes')
  1482.         IF (Char(page+3) AND %00000001) = 1 THEN outlist('\ebStandby Support Enabled:\en', 'Yes') ELSE outlist('\ebStandby Support Enabled:\en', 'No')
  1483.         outlist_i('\ebIdle Time to enter Standby:\en', Long(page+8), ' *100 Ms')
  1484.     ELSE
  1485.         outlist('\ebInformation Page:\en', 'Unsupported or Reserved for this device class')
  1486.         outlist('\ebPage Code:\en', '13 ($D)')
  1487.     ENDIF
  1488.  
  1489. ENDPROC
  1490.  
  1491.  
  1492. /*
  1493. ** Handler for a specific mode page
  1494. */
  1495. PROC process_modesense_E(page)
  1496.  
  1497.     IF global_devtype=DEV_CDROM
  1498.         outlist('\ebInformation Page:\en', 'CD-ROM Audio Parameters')
  1499.         outlist('\ebPage Code:\en', '14 ($E)')
  1500.         outlist_i('\ebPage Length:\en', Char(page+1), ' bytes')
  1501.         IF (Char(page+2) AND %00000100) = 4 THEN outlist('\ebAudio Completion Status:\en', 'On Audio Termination') ELSE outlist('\ebAudio Completion Status:\en', 'On Audio Playback')
  1502.         IF (Char(page+2) AND %00000010) = 2 THEN outlist('\ebStop on Track Crossing:\en', 'When next track encountered') ELSE outlist('\ebStop on Track Crossing:\en', 'When transfer length satisfied')
  1503.         outlist_i('\ebFormat of LBA/sec:\en', (Char(page+5) AND $00001111), NIL)
  1504.         outlist_i('\ebLBA/sec per audio:\en', Int(page+6), NIL)
  1505.         outlist_i('\ebPort 0 Volume Level:\en', Char(page+9), NIL)
  1506.         outlist_i('\ebPort 1 Volume Level:\en', Char(page+11), NIL)
  1507.         outlist_i('\ebPort 2 Volume Level:\en', Char(page+13), NIL)
  1508.         outlist_i('\ebPort 3 Volume Level:\en', Char(page+15), NIL)
  1509.     ELSE
  1510.         outlist('\ebInformation Page:\en', 'Unsupported or Reserved for this device class')
  1511.         outlist('\ebPage Code:\en', '14 ($E)')
  1512.     ENDIF
  1513.  
  1514. ENDPROC
  1515.  
  1516.  
  1517. /*
  1518. ** Handler for a specific mode page
  1519. */
  1520. PROC process_modesense_F(page)
  1521.  
  1522.     IF global_devtype=DEV_SEQUENTIAL
  1523.         outlist('\ebVendor Information Page:\en', 'Data Compression Characteristics')
  1524.         outlist('\ebCAUTION:\en', 'Vendor Specific Page Decoded')
  1525.         outlist('\ebREFERENCE:\en', 'HP C1533A')
  1526.         outlist('\ebPage Code:\en', '15 ($F)')
  1527.         outlist_i('\ebPage Length:\en', Char(page+1), ' bytes')
  1528.         IF (Char(page+2) AND %10000000)=128 THEN outlist('\ebData Compression Enabled:\en', 'Yes') ELSE outlist('\ebData Compression Enabled:\en', 'No')
  1529.         IF (Char(page+2) AND %01000000)=64 THEN outlist('\ebData Compression Supported:\en', 'Yes') ELSE outlist('\ebData Compression Supported:\en', 'No')
  1530.         IF (Char(page+3) AND %10000000)=128 THEN outlist('\ebAttempt Decompression:\en', 'Yes') ELSE outlist('\ebAttempt Decompression:\en', 'No')
  1531.         outlist_i('\ebCompression Algorithm:\en', Long(page+4), NIL)
  1532.         outlist_i('\ebDecompression Algorithm:\en', Long(page+8), NIL)
  1533.     ELSE
  1534.         outlist('\ebInformation Page:\en', 'Unsupported or Reserved for this device class')
  1535.         outlist('\ebPage Code:\en', '26 ($1A)')
  1536.     ENDIF
  1537.  
  1538. ENDPROC
  1539.  
  1540.  
  1541. /*
  1542. ** Handler for a specific mode page
  1543. */
  1544. PROC process_modesense_10(page)
  1545.  
  1546.     IF global_devtype=DEV_SEQUENTIAL
  1547.         outlist('\ebInformation Page:\en', 'Sequential Device Configuration')
  1548.         outlist('\ebPage Code:\en', '16 ($10)')
  1549.         outlist_i('\ebPage Length:\en', Char(page+1), ' bytes')
  1550.         outlist_i('\ebActive Recording Format:\en', (Char(page+2) AND %00011111), ' (All values are vendor specific)')
  1551.         outlist_i('\ebActive Logical Partition:\en', Char(page+3), NIL)
  1552.         outlist_i('\ebWrite Buffer Ratio:\en', Char(page+4), NIL)
  1553.         outlist_i('\ebRead Buffer Ratio:\en', Char(page+5), NIL)
  1554.         outlist_i('\ebWrite Delay:\en', Int(page+6), ' *100 Ms')
  1555.         IF (Char(page+8) AND %10000000) = 128 THEN outlist('\ebData Buffer Recovery:\en', 'Enabled') ELSE outlist('\ebData Buffer Recovery:\en', 'Disabled or not supported')
  1556.         IF (Char(page+8) AND %00100000) = 32 THEN outlist('\ebSetMarks:\en', 'Enabled') ELSE outlist('\ebSetMarks:\en', 'Disabled or not supported')
  1557.         IF (Char(page+8) AND %00010000) = 16 THEN outlist('\ebAutomatic Velocity Control:\en', 'Yes') ELSE outlist('\ebAutomatic Velocity Control:\en', 'No')
  1558.         IF (Char(page+8) AND %00000010) = 2 THEN outlist('\ebRecovery Buffer Order:\en', 'LIFO') ELSE outlist('\ebRecovery Buffer Order:\en', 'FIFO')
  1559.         IF Char(page+9) = 0 THEN outlist('\ebGap Size:\en', 'Device Default') ELSE outlist_i('\ebGap Size:\en', Char(page+9), NIL)
  1560.         IF Char(page+14) = 0 
  1561.             outlist('\ebCompression:\en', 'Disabled or not supported')
  1562.         ELSEIF  Char(page+14) = 1
  1563.             outlist('\ebCompression:\en', 'Enabled')
  1564.         ENDIF
  1565.     ELSE
  1566.         outlist('\ebInformation Page:\en', 'Unsupported or Reserved for this device class')
  1567.         outlist('\ebPage Code:\en', '16 ($10)')
  1568.     ENDIF
  1569.  
  1570. ENDPROC
  1571.  
  1572.  
  1573. /*
  1574. ** Handler for a specific mode page
  1575. */
  1576. PROC process_modesense_11(page)
  1577.  
  1578.     IF global_devtype=DEV_SEQUENTIAL
  1579.         outlist('\ebInformation Page:\en', 'Medium Partition Page (1)')
  1580.         outlist('\ebPage Code:\en', '17 ($11)')
  1581.         outlist_i('\ebPage Length:\en', Char(page+1), ' bytes')
  1582.         outlist_i('\ebMax Additional Partitions:\en', Char(page+2), NIL)
  1583.         outlist_i('\ebAdditional Partitions Defined:\en', Char(page+3), NIL)
  1584.         IF (Char(page+4) AND %00011000) = 0
  1585.             outlist('\ebPartition Unit of Measure:\en', 'Bytes')
  1586.         ELSEIF (Char(page+4) AND %00011000) = 1
  1587.             outlist('\ebPartition Unit of Measure:\en', 'KiloBytes')
  1588.         ELSEIF (Char(page+4) AND %00011000) = 2
  1589.             outlist('\ebPartition Unit of Measure:\en', 'MegaBytes')
  1590.         ELSE
  1591.             outlist('\ebPartition Unit of Measure:\en', 'Custom')
  1592.         ENDIF
  1593.         IF Char(page+5)=0
  1594.             outlist('\ebMedium Format Recognition:\en', 'Incapable of Format or Partition Recognition')
  1595.         ELSEIF Char(page+5)=1
  1596.             outlist('\ebMedium Format Recognition:\en', 'Format Recognition Only')
  1597.         ELSEIF Char(page+5)=2
  1598.             outlist('\ebMedium Format Recognition:\en', 'Partition Recognition Only')
  1599.         ELSEIF Char(page+5)=3
  1600.             outlist('\ebMedium Format Recognition:\en', 'Format and Partition Recognition')
  1601.         ELSE
  1602.             outlist('\ebMedium Format Recognition:\en', 'Reserved')
  1603.         ENDIF
  1604.     ELSE
  1605.         outlist('\ebInformation Page:\en', 'Unsupported or Reserved for this device class')
  1606.         outlist('\ebPage Code:\en', '17 ($11)')
  1607.     ENDIF
  1608.  
  1609.  
  1610. ENDPROC
  1611.  
  1612.  
  1613. /*
  1614. ** Handler for a specific mode page
  1615. */
  1616. PROC process_modesense_12(page)
  1617.  
  1618.    IF global_devtype=DEV_SEQUENTIAL
  1619.         outlist('\ebInformation Page:\en', 'Medium Partition Page (2)')
  1620.         outlist('\ebPage Code:\en', '18 ($12)')
  1621.         outlist_i('\ebPage Length:\en', Char(page+1), ' bytes')
  1622.     ELSE
  1623.         outlist('\ebInformation Page:\en', 'Unsupported or Reserved for this device class')
  1624.         outlist('\ebPage Code:\en', '18 ($12)')
  1625.     ENDIF
  1626.  
  1627. ENDPROC
  1628.  
  1629.  
  1630. /*
  1631. ** Handler for a specific mode page
  1632. */
  1633. PROC process_modesense_13(page)
  1634.  
  1635.    IF global_devtype=DEV_SEQUENTIAL
  1636.         outlist('\ebInformation Page:\en', 'Medium Partition Page (3)')
  1637.         outlist('\ebPage Code:\en', '19 ($13)')
  1638.         outlist_i('\ebPage Length:\en', Char(page+1), ' bytes')
  1639.     ELSE
  1640.         outlist('\ebInformation Page:\en', 'Unsupported or Reserved for this device class')
  1641.         outlist('\ebPage Code:\en', '19 ($13)')
  1642.     ENDIF
  1643.  
  1644. ENDPROC
  1645.  
  1646.  
  1647. /*
  1648. ** Handler for a specific mode page
  1649. */
  1650. PROC process_modesense_14(page)
  1651.  
  1652.    IF global_devtype=DEV_SEQUENTIAL
  1653.         outlist('\ebInformation Page:\en', 'Medium Partition Page (4)')
  1654.         outlist('\ebPage Code:\en', '20 ($14)')
  1655.         outlist_i('\ebPage Length:\en', Char(page+1), ' bytes')
  1656.     ELSE
  1657.         outlist('\ebInformation Page:\en', 'Unsupported or Reserved for this device class')
  1658.         outlist('\ebPage Code:\en', '20 ($14)')
  1659.     ENDIF
  1660.  
  1661. ENDPROC
  1662.  
  1663.  
  1664. /*
  1665. ** Handler for a specific mode page
  1666. */
  1667. PROC process_modesense_18(page)
  1668.     outlist('\ebInformation Page:\en', 'Protocol Specific LUN')
  1669.     outlist('\ebPage Code:\en', '24 ($18)')
  1670.     outlist_i('\ebPage Length:\en', Char(page+1), ' bytes')
  1671.     IF (Char(page+2) AND %00001111) = 0
  1672.         outlist('\ebProtocol Identifier:\en', 'Fibre Channel')
  1673.     ELSEIF (Char(page+2) AND %00001111) = 1
  1674.         outlist('\ebProtocol Identifier:\en', 'Parallel SCSI')
  1675.     ELSEIF (Char(page+2) AND %00001111) = 2
  1676.         outlist('\ebProtocol Identifier:\en', 'SSA (S2P or S3P)')
  1677.     ELSEIF (Char(page+2) AND %00001111) = 1
  1678.         outlist('\ebProtocol Identifier:\en', 'IEEE 1394 (SBP-2/Firewire)')
  1679.     ELSE
  1680.         outlist('\ebProtocol Identifier:\en', 'Reserved')
  1681.     ENDIF
  1682. ENDPROC
  1683.  
  1684.  
  1685. /*
  1686. ** Handler for a specific mode page
  1687. */
  1688. PROC process_modesense_19(page)
  1689.     outlist('\ebInformation Page:\en', 'Protocol Specifics')
  1690.     outlist('\ebPage Code:\en', '25 ($19)')
  1691.     outlist_i('\ebPage Length:\en', Char(page+1), ' bytes')
  1692.     IF (Char(page+2) AND %00001111) = 0
  1693.         outlist('\ebProtocol Identifier:\en', 'Fibre Channel')
  1694.     ELSEIF (Char(page+2) AND %00001111) = 1
  1695.         outlist('\ebProtocol Identifier:\en', 'Parallel SCSI')
  1696.     ELSEIF (Char(page+2) AND %00001111) = 2
  1697.         outlist('\ebProtocol Identifier:\en', 'SSA (S2P or S3P)')
  1698.     ELSEIF (Char(page+2) AND %00001111) = 1
  1699.         outlist('\ebProtocol Identifier:\en', 'IEEE 1394 (SBP-2/Firewire)')
  1700.     ELSE
  1701.         outlist('\ebProtocol Identifier:\en', 'Reserved')
  1702.     ENDIF
  1703. ENDPROC
  1704.  
  1705.  
  1706. /*
  1707. ** Handler for a specific mode page
  1708. */
  1709. PROC process_modesense_1A(page)
  1710.  
  1711.     outlist('\ebInformation Page:\en', 'Power Condition')
  1712.     outlist('\ebPage Code:\en', '26 ($1A)')
  1713.     outlist_i('\ebPage Length:\en', Char(page+1), ' bytes')
  1714.     IF (Char(page+3) AND %00000001) = 1 THEN outlist('\ebStandby Support Enabled:\en', 'Yes') ELSE outlist('\ebStandby Support Enabled:\en', 'No')
  1715.     outlist_i('\ebIdle Time to enter Standby:\en', Long(page+8), ' *100 Ms')
  1716.  
  1717. ENDPROC
  1718.  
  1719.  
  1720. /*
  1721. ** Handler for a specific mode page
  1722. */
  1723. PROC process_modesense_1C(page)
  1724.  
  1725.     outlist('\ebInformation Page:\en', 'SCSI SMART Control')
  1726.     outlist('\ebPage Code:\en', '28 ($1C)')
  1727.     outlist_i('\ebPage Length:\en', Char(page+1), ' bytes')
  1728.     IF (Char(page+2) AND %00000001) = 1 THEN outlist('\ebInfo Exception Logs:\en', 'in Firmware Logs') ELSE outlist('\ebInfo Exception Logs:\en', 'in Vendor Specific Location')
  1729.     IF (Char(page+2) AND %00001000) = 8 THEN outlist('\ebException Control:\en', 'Disabled') ELSE outlist('\ebException Control:\en', 'Enabled')
  1730.     IF (Char(page+3) AND %00001111) = $0
  1731.         outlist('\ebReporting Type:\en', 'None')
  1732.     ELSEIF (Char(page+3) AND %00001111) = $1
  1733.         outlist('\ebReporting Type:\en', 'Asynchronous Event')
  1734.     ELSEIF (Char(page+3) AND %00001111) = $2
  1735.         outlist('\ebReporting Type:\en', 'Generate Unit Attention')
  1736.     ELSEIF (Char(page+3) AND %00001111) = $3
  1737.         outlist('\ebReporting Type:\en', 'Conditionally Generate Recovered Err')
  1738.     ELSEIF (Char(page+3) AND %00001111) = $4
  1739.         outlist('\ebReporting Type:\en', 'Unconditionally Generate Recovered Err')
  1740.     ELSEIF (Char(page+3) AND %00001111) = $5
  1741.         outlist('\ebReporting Type:\en', 'Generate No Sense')
  1742.     ELSEIF (Char(page+3) AND %00001111) = $6
  1743.         outlist('\ebReporting Type:\en', 'Only on Request')
  1744.     ELSE
  1745.         outlist('\ebReporting Type:\en', 'Vendor Specific')
  1746.     ENDIF
  1747.     outlist_i('\ebInterval Timer:\en', Long(page+4), NIL)
  1748.     outlist_i('\ebReport Count:\en', Long(page+8), NIL)
  1749.  
  1750. ENDPROC
  1751.  
  1752.  
  1753. /*
  1754. ** Handler for a specific mode page
  1755. */
  1756. PROC process_modesense_2A(page)
  1757.  
  1758.     IF global_devtype=DEV_CDROM
  1759.         outlist('\ebVendor Information Page:\en', 'CDROM Capabilities and Mechanical Status')
  1760.         outlist('\ebPage Code:\en', '42 ($2A)')
  1761.         outlist_i('\ebPage Length:\en', Char(page+1), ' bytes')
  1762.         outlist_i('\ebMaximum Supported Speed:\en', Int(page+8),' kbyte/sec')
  1763.         outlist_i('\ebMinimum Supported Speed:\en', Int(page+10), ' kbyte/sec')
  1764.         outlist_i('\ebBuffer Size:\en', Int(page+12), ' K')
  1765.         outlist_i('\ebCurrent Selected Speed:\en', Int(page+14), ' kbyte/sec')
  1766.     ELSE
  1767.         outlist('\ebInformation Page:\en', 'Unsupported or Reserved for this device class')
  1768.         outlist('\ebPage Code:\en', '42 ($2A)')
  1769.     ENDIF
  1770.  
  1771. ENDPROC
  1772.  
  1773.  
  1774. /*
  1775. ** Handler for a specific mode page
  1776. */
  1777. PROC process_modesense_21(page)
  1778.  
  1779.    IF global_devtype=DEV_DIRECT
  1780.         outlist('\ebVendor Information Page:\en', 'Extended Error Recovery')
  1781.         outlist('\ebCAUTION:\en', 'Vendor Specific Page Decoded')
  1782.         outlist('\ebREFERENCE:\en', 'FUJITSU MAB 3091SC, MAE 3182LC, MAG 3091L')
  1783.         outlist('\ebPage Code:\en', '33 ($21)')
  1784.         outlist_i('\ebPage Length:\en', Char(page+1), ' bytes')
  1785.         outlist_i('\ebRetry Count on Seek Error:\en', Char(page+2), '')
  1786.     ELSE
  1787.         outlist('\ebInformation Page:\en', 'Unsupported or Reserved for this device class')
  1788.         outlist('\ebPage Code:\en', '33 ($21)')
  1789.     ENDIF
  1790.  
  1791. ENDPROC
  1792.  
  1793.  
  1794.  
  1795.  
  1796. /*
  1797. ** Handler for a specific mode page
  1798. */
  1799. PROC process_modesense_39(page)
  1800.  
  1801.     IF global_devtype=DEV_DIRECT
  1802.         outlist('\ebVendor Information Page:\en', 'Quantum Unique Drive Control')
  1803.         outlist('\ebCAUTION:\en', 'Vendor Specific Page Decoded')
  1804.         outlist('\ebREFERENCE:\en', 'Quantum Fireball ST 2.1/3.2/4.3/6.4 GB S')
  1805.         outlist('\ebPage Code:\en', '57 ($39)')
  1806.         outlist_i('\ebPage Length:\en', Char(page+1), ' bytes')
  1807.         IF (Char(page+2) AND %10000000) = 128 THEN outlist('\ebDisable Identify Out:\en', 'Yes') ELSE outlist('\ebDisable Identify Out:\en', 'No')
  1808.         IF (Char(page+2) AND %01000000) = 64 THEN outlist('\ebDisable Identify In:\en', 'Yes') ELSE outlist('\ebDisable Identify In:\en', 'No')
  1809.         IF (Char(page+2) AND %00100000) = 32 THEN outlist('\ebPreserve Synchronous Mode:\en', 'Yes') ELSE outlist('\ebPreserve Synchronous Mode:\en', 'No')
  1810.         IF (Char(page+2) AND %00010000) = 16 THEN outlist('\ebReallocate Uncorrectable Errors:\en', 'Yes') ELSE outlist('\ebReallocate Uncorrectable Errors:\en', 'No')
  1811.         IF (Char(page+2) AND %00001000) = 8 THEN outlist('\ebFill Data Pattern:\en', 'Enabled') ELSE outlist('\ebFill Data Pattern:\en', 'Disabled')
  1812.         IF (Char(page+2) AND %00000100) = 4 THEN outlist('\ebSend Synchronous Message:\en', 'Yes') ELSE outlist('\ebSend Synchronous Message:\en', 'No')
  1813.         IF (Char(page+2) AND %00000010) = 2 THEN outlist('\ebDisable Unit Attention:\en', 'Yes') ELSE outlist('\ebDisable Unit Attention:\en', 'No')
  1814.         IF (Char(page+2) AND %00000001) = 1 THEN outlist('\ebDisable Reselection Timeout:\en', 'Yes') ELSE outlist('\ebDisable Reselection Timeout:\en', 'No')
  1815.         IF (Char(page+3) AND %10000000) = 128 THEN outlist('\ebDisable Disconnection:\en', 'Yes') ELSE outlist('\ebDisable Disconnection:\en', 'No')
  1816.         IF (Char(page+3) AND %00001000) = 8 THEN outlist('\ebSoftware Selectable SCSI ID:\en', 'Enabled') ELSE outlist('\ebSoftware Selectable SCSI ID:\en', 'Disabled')
  1817.         outlist_i('\ebSoftware SCSI ID:\en', (Char(page+3) AND %00000111), NIL)
  1818.         IF (Char(page+4) AND %00010000) = 16 THEN outlist('\ebDisable Plug n Play SCSI:\en', 'Yes')  ELSE outlist('\ebDisable Plug n Play SCSI:\en', 'No')
  1819.         IF (Char(page+4) AND %00001000) = 8 THEN outlist('\ebUse Motor Delay Time:\en', 'Yes') ELSE outlist('\ebUse Motor Delay Time:\en', 'No')
  1820.         IF (Char(page+4) AND %00000010) = 2 THEN outlist('\ebDisable Parity Control:\en', 'Yes') ELSE outlist('\ebDisable Parity Control:\en', 'No')
  1821.         IF (Char(page+4) AND %00000001) = 1 THEN outlist('\ebPerform Wait/Spin:\en', 'Yes') ELSE outlist('\ebPerform Wait/Spin:\en', 'No')
  1822.         outlist_i('\ebMotor Delay Time:\en', Char(page+5), ' *10 Ms')
  1823.     ELSE
  1824.         outlist('\ebInformation Page:\en', 'Unsupported or Reserved for this device class')
  1825.         outlist('\ebPage Code:\en', '57 ($39)')
  1826.     ENDIF
  1827.  
  1828. ENDPROC
  1829.  
  1830.  
  1831. /*
  1832. ** Handler processing the data returned when requesting a list of known logs
  1833. ** It then calls the handler processes for each known log type
  1834. */
  1835. PROC process_log_support(reply:PTR TO l_sense)
  1836. DEF x=0
  1837.  
  1838.     outlist_i('\ebLog Size:\en', reply.len, ' bytes')
  1839.     outlist(' ', ' ')
  1840.  
  1841.     FOR x:=0 TO (reply.len-1)
  1842.         SELECT $3F OF Char(reply+x+4)
  1843.             CASE $0
  1844.                 ->No real point in listing it, we know the disk supports it or we wouldn't get a reply
  1845.                 ->outlist_h('\ebFound Log:\en', Char(reply+x+4), ':  List of supported log types')
  1846.             CASE $1
  1847.                 outlist('\ebFound Log:\en', 'Buffer Over-run and Under-run Log')
  1848.                 outlist_h('\ebLog Code:\en', Char(reply+x+4), ' ')
  1849.                 query(driver, Val(unit), [SCSI_LOG_SENSE, 0, P_LOG_BUFFER, 0, 0, 0, 0, 0, BUFFSIZE, 0]:cdb10, SIZEOF cdb10, NIL)
  1850.                 outlist(' ', ' ')
  1851.             CASE $2
  1852.                 outlist('\ebFound Log:\en', 'Write Error Log')
  1853.                 outlist_h('\ebLog Code:\en', Char(reply+x+4), ' ')
  1854.                 query(driver, Val(unit), [SCSI_LOG_SENSE, 0, P_LOG_WRITE, 0, 0, 0, 0, 0, BUFFSIZE, 0]:cdb10, SIZEOF cdb10, NIL)
  1855.                 outlist(' ', ' ')
  1856.             CASE $3
  1857.                 outlist('\ebFound Log:\en', 'Read Error Log')
  1858.                 outlist_h('\ebLog Code:\en', Char(reply+x+4), ' ')
  1859.                 query(driver, Val(unit), [SCSI_LOG_SENSE, 0, P_LOG_READ, 0, 0, 0, 0, 0, BUFFSIZE, 0]:cdb10, SIZEOF cdb10, NIL)
  1860.                 outlist(' ', ' ')
  1861.             CASE $4
  1862.                 outlist('\ebFound Log:\en', 'Reverse-Read Error Log')
  1863.                 outlist_h('\ebLog Code:\en', Char(reply+x+4), ' ')
  1864.                 query(driver, Val(unit), [SCSI_LOG_SENSE, 0, P_LOG_REVREAD, 0, 0, 0, 0, 0, BUFFSIZE, 0]:cdb10, SIZEOF cdb10, NIL)
  1865.                 outlist(' ', ' ')
  1866.             CASE $5
  1867.                 outlist('\ebFound Log:\en', 'Verify Error Log')
  1868.                 outlist_h('\ebLog Code:\en', Char(reply+x+4), ' ')
  1869.                 query(driver, Val(unit), [SCSI_LOG_SENSE, 0, P_LOG_VERIFY, 0, 0, 0, 0, 0, BUFFSIZE, 0]:cdb10, SIZEOF cdb10, NIL)
  1870.                 outlist(' ', ' ')
  1871.             CASE $6
  1872.                 outlist('\ebFound Log:\en', 'Non-medium Error Log')
  1873.                 outlist_h('\ebLog Code:\en', Char(reply+x+4), ' ')
  1874.                 query(driver, Val(unit), [SCSI_LOG_SENSE, 0, P_LOG_NMERRORS, 0, 0, 0, 0, 0, BUFFSIZE, 0]:cdb10, SIZEOF cdb10, NIL)
  1875.                 outlist(' ', ' ')
  1876.             CASE $7
  1877.                 outlist('\ebFound Log:\en', 'Last # of Error Events Log')
  1878.                 outlist_h('\ebLog Code:\en', Char(reply+x+4), ' (Cannot Decode Yet)')
  1879.                 outlist(' ', ' ')
  1880.             CASE $8
  1881.                 outlist('\ebFound Log:\en', 'Format Status')
  1882.                 outlist_h('\ebLog Code:\en', Char(reply+x+4), ' (Cannot Decode Yet)')
  1883.                 outlist(' ', ' ')
  1884.             CASE $9
  1885.                 outlist('\ebFound Log:\en', 'Reserved to the MS59 Standard')
  1886.                 outlist_h('\ebLog Code:\en', Char(reply+x+4), ' (Cannot Decode Yet)')
  1887.                 outlist(' ', ' ')
  1888.             CASE $A
  1889.                 outlist('\ebFound Log:\en', 'Reserved to the MS59 Standard')
  1890.                 outlist_h('\ebLog Code:\en', Char(reply+x+4), ' (Cannot Decode Yet)')
  1891.                 outlist(' ', ' ')
  1892.             CASE $B
  1893.                 outlist('\ebFound Log:\en', 'Last # deferred errors or Async Events')
  1894.                 outlist_h('\ebLog Code:\en', Char(reply+x+4), ' (Cannot Decode Yet)')
  1895.                 outlist(' ', ' ')
  1896.             CASE $C
  1897.                 outlist('\ebFound Log:\en', 'Sequential Access Log')
  1898.                 outlist_h('\ebLog Code:\en', Char(reply+x+4), ' (Cannot Decode Yet)')
  1899.                 outlist(' ', ' ')
  1900.             CASE $D
  1901.                 outlist('\ebFound Log:\en', 'Temperature Log')
  1902.                 outlist_h('\ebLog Code:\en', Char(reply+x+4), ' ')
  1903.                 query(driver, Val(unit), [SCSI_LOG_SENSE, 0, P_LOG_TEMPERATURE, 0, 0, 0, 0, 0, BUFFSIZE, 0]:cdb10, SIZEOF cdb10, NIL)
  1904.                 outlist(' ', ' ')
  1905.             CASE $E
  1906.                 outlist('\ebFound Log:\en', 'Start Stop Cycle Log')
  1907.                 outlist_h('\ebLog Code:\en', Char(reply+x+4), ' (Cannot Decode Yet)')
  1908.                 outlist(' ', ' ')
  1909.             CASE $F
  1910.                 outlist('\ebFound Log:\en', 'Application Client Log')
  1911.                 outlist_h('\ebLog Code:\en', Char(reply+x+4), ' (Cannot Decode Yet)')
  1912.                 outlist(' ', ' ')
  1913.             CASE $10
  1914.                 outlist('\ebFound Log:\en', 'Self Test Results')
  1915.                 outlist_h('\ebLog Code:\en', Char(reply+x+4), ' (Cannot Decode Yet)')
  1916.                 outlist(' ', ' ')
  1917.             CASE $11
  1918.                 outlist('\ebFound Log:\en', 'DTD Status Log')
  1919.                 outlist_h('\ebLog Code:\en', Char(reply+x+4), ' (Cannot Decode Yet)')
  1920.                 outlist(' ', ' ')
  1921.             CASE $12
  1922.                 outlist('\ebFound Log:\en', 'Tape Alert Response')
  1923.                 outlist_h('\ebLog Code:\en', Char(reply+x+4), ' (Cannot Decode Yet)')
  1924.                 outlist(' ', ' ')
  1925.             CASE $13
  1926.                 outlist('\ebFound Log:\en', 'Requested Recovery Log')
  1927.                 outlist_h('\ebLog Code:\en', Char(reply+x+4), ' (Cannot Decode Yet)')
  1928.                 outlist(' ', ' ')
  1929.             CASE $14
  1930.                 outlist('\ebFound Log:\en', 'Device Statistics')
  1931.                 outlist_h('\ebLog Code:\en', Char(reply+x+4), ' (Cannot Decode Yet)')
  1932.                 outlist(' ', ' ')
  1933.             CASE $17
  1934.                 outlist('\ebFound Log:\en', 'Non-Volatile Cache')
  1935.                 outlist_h('\ebLog Code:\en', Char(reply+x+4), ' (Cannot Decode Yet)')
  1936.                 outlist(' ', ' ')
  1937.             CASE $18
  1938.                 outlist('\ebFound Log:\en', 'Protocol Specific Port')
  1939.                 outlist_h('\ebLog Code:\en', Char(reply+x+4), ' (Cannot Decode Yet)')
  1940.                 outlist(' ', ' ')
  1941.             CASE $2E
  1942.                 outlist('\ebFound Log:\en', 'TapeAlert Log')
  1943.                 outlist_h('\ebLog Code:\en', Char(reply+x+4), ' (Cannot Decode Yet)')
  1944.             CASE $2F
  1945.                 outlist('\ebFound Log:\en', 'Informational Exceptions')
  1946.                 outlist_h('\ebLog Code:\en', Char(reply+x+4), NIL)
  1947.                 query(driver, Val(unit), [SCSI_LOG_SENSE, 0, P_LOG_IE, 0, 0, 0, 0, 0, BUFFSIZE, 0]:cdb10, SIZEOF cdb10, NIL)
  1948.                 outlist(' ', ' ')
  1949.             CASE $30
  1950.                 outlist('\ebFound Log:\en', 'SMART Data Sense')
  1951.                 outlist_h('\ebLog Code:\en', Char(reply+x+4), ' (Cannot Decode Yet)')
  1952.                 outlist(' ', ' ')
  1953.             CASE $37
  1954.                 outlist('\ebFound Log:\en', 'Cache Statistics (Seagate)')
  1955.                 outlist_h('\ebLog Code:\en', Char(reply+x+4), ' (Cannot Decode Yet)')
  1956.                 outlist(' ', ' ')
  1957.             CASE $3E
  1958.                 outlist('\ebFound Log:\en', 'Factory Log (Seagate)')
  1959.                 outlist_h('\ebLog Code:\en', Char(reply+x+4), ' (Cannot Decode yet)')
  1960.                 outlist(' ', ' ')
  1961.             DEFAULT
  1962.                 outlist('\ebFound Log:\en', 'Unknown Vendor Log')
  1963.                 outlist_h('\ebLog Code:\en', Char(reply+x+4), ' (Cannot Decode)')
  1964.                 outlist(' ', ' ')
  1965.         ENDSELECT
  1966.     ENDFOR
  1967. ENDPROC
  1968.  
  1969.  
  1970. /*
  1971. ** Handler for processing varios error logs.
  1972. */
  1973. PROC process_log_errors(reply:PTR TO l_sense)
  1974. DEF param:PTR TO l_param, plen=0, buildstr[100]:STRING
  1975.  
  1976.     outlist_i('\ebLog Size:\en', reply.len, ' bytes')
  1977.     param:=reply + (SIZEOF l_sense)
  1978.  
  1979.     WHILE param < (reply + reply.len + SIZEOF l_sense)
  1980.         SELECT $FF OF param.pcode2
  1981.             CASE $0
  1982.                 StrCopy(buildstr, '\ebErrors Corrected w/o Delay:\en')
  1983.             CASE $1
  1984.                 StrCopy(buildstr, '\ebErrors Corrected w/ Delay:\en')
  1985.             CASE $2
  1986.                 StrCopy(buildstr, '\ebTotal Re-writes or Re-reads:\en')
  1987.             CASE $3
  1988.                 StrCopy(buildstr, '\ebTotal Errors Corrected:\en')
  1989.             CASE $4
  1990.                 StrCopy(buildstr, '\ebTimes Correction Algorithm Used:\en')
  1991.             CASE $5
  1992.                 StrCopy(buildstr, '\ebTotal Bytes Processed:\en')
  1993.             CASE $6
  1994.                 StrCopy(buildstr, '\ebUncorrected Errors:\en')
  1995.             DEFAULT
  1996.                 StrCopy(buildstr, '\ebVendor Parameter\en:')
  1997.         ENDSELECT
  1998.  
  1999.         plen:=param.len
  2000.         param:=param + (SIZEOF l_param) 
  2001.  
  2002.         IF plen = 1
  2003.             outlist_i(buildstr, Char(param), NIL)
  2004.         ELSEIF plen = 2
  2005.             outlist_i(buildstr, Int(param), NIL)
  2006.         ELSEIF plen = 4
  2007.             outlist_i(buildstr, Long(param), NIL)
  2008.         ELSEIF plen = 8
  2009.             outlist_i(buildstr, Long(param), ' (First longword)')
  2010.             outlist_i(' ', Long(param+4), ' (Second longword)')
  2011.         ELSE
  2012.             outlist(buildstr, 'Cannot Decode')
  2013.         ENDIF
  2014.  
  2015.         param:=param + plen
  2016.  
  2017.     ENDWHILE
  2018.  
  2019. ENDPROC
  2020.  
  2021.  
  2022. /*
  2023. ** Handler for processing non medium error logs
  2024. */
  2025. PROC process_log_nmerrors(reply:PTR TO l_sense)
  2026. DEF param:PTR TO l_param, plen=0, buildstr[100]:STRING
  2027.  
  2028.     outlist_i('\ebLog Size:\en', reply.len, ' bytes')
  2029.     param:=reply + (SIZEOF l_sense)
  2030.  
  2031.     WHILE param < (reply + reply.len + SIZEOF l_sense)
  2032.         
  2033.         SELECT $FF OF param.pcode2
  2034.             CASE $0
  2035.                 StrCopy(buildstr, '\ebNon-Medium Error Count:\en')
  2036.             DEFAULT
  2037.                 StrCopy(buildstr, '\ebVendor Parameter:\en')
  2038.         ENDSELECT
  2039.  
  2040.         plen:=param.len
  2041.         param:=param + (SIZEOF l_param)
  2042.  
  2043.         IF plen = 1
  2044.             outlist_i(buildstr, Char(param), NIL)
  2045.         ELSEIF plen = 2
  2046.             outlist_i(buildstr, Int(param), NIL)
  2047.         ELSEIF plen = 4
  2048.             outlist_i(buildstr, Long(param), NIL)
  2049.         ELSEIF plen = 8
  2050.             outlist_i(buildstr, Long(param), ' (Lower longword)')
  2051.             outlist_i(' ', Long(param+4), ' (Upper longword)')
  2052.         ELSE
  2053.             outlist(buildstr, 'Cannot Decode')
  2054.         ENDIF
  2055.  
  2056.         param:=param + plen
  2057.  
  2058.     ENDWHILE
  2059.  
  2060. ENDPROC
  2061.  
  2062.  
  2063. /*
  2064. ** Handler for processing buffer logs
  2065. */
  2066. PROC process_log_buffer(reply:PTR TO l_sense)
  2067. DEF param:PTR TO lb_param
  2068.  
  2069.     outlist_i('\ebLog Size:\en', reply.len, ' bytes')
  2070.     param:=reply + SIZEOF l_sense
  2071.  
  2072.     WHILE (param < (reply + reply.len + SIZEOF l_sense))
  2073.  
  2074.     IF (param.counter AND %00000001) = 0
  2075.         outlist('\ebType:\en', 'Buffer Under-Run')
  2076.     ELSE
  2077.         outlist('\ebType:\en', 'Buffer Over-Run')
  2078.     ENDIF
  2079.  
  2080.     IF (param.counter AND %00011110) = 0
  2081.         outlist('\ebCause:\en', 'Undefined')
  2082.     ELSEIF (param.counter AND %00011110) = 2
  2083.         outlist('\ebCause:\en', 'Bus Busy')
  2084.     ELSEIF (param.counter AND %00011110) = 4
  2085.         outlist('\ebCause:\en', 'Transfer Rate Too Slow')
  2086.     ELSE
  2087.         outlist('\ebCause:\en', 'Reserved')
  2088.     ENDIF
  2089.  
  2090.     IF (param.counter AND %11100000) = 0
  2091.         outlist('\ebCount Basis:\en', 'Undefined')
  2092.     ELSEIF (param.counter AND %11100000) = 32
  2093.         outlist('\ebCount Basis:\en', 'Per command')
  2094.     ELSEIF (param.counter AND %11100000) = 64
  2095.         outlist('\ebCount Basis:\en', 'Per failed reconnect')
  2096.     ELSEIF (param.counter AND %11100000) = 96
  2097.         outlist('\ebCount Basis:\en', 'Per unit of time')
  2098.     ELSE
  2099.         outlist('\ebCount Basis:\en', 'Reserved')
  2100.     ENDIF
  2101.  
  2102.     param := param + SIZEOF lb_param
  2103.  
  2104.     ENDWHILE
  2105.  
  2106. ENDPROC
  2107.  
  2108. /*
  2109. ** Handler for processing information exception logs
  2110. */
  2111. PROC process_log_ie(reply:PTR TO l_sense)
  2112. DEF param:PTR TO lie_param
  2113.  
  2114.     outlist_i('\ebLog Size:\en', reply.len, NIL)
  2115.     param:=reply + SIZEOF lie_param
  2116.  
  2117.     WHILE (param < (reply + reply.len + SIZEOF l_sense))
  2118.         outlist_i('\ebParameter Code:\en', param.pcode, NIL)
  2119.         outlist_i('\ebParameter Size:\en', param.len, ' bytes')
  2120.         param:= param + (SIZEOF lie_param) + param.len
  2121.     ENDWHILE
  2122.  
  2123. ENDPROC
  2124.  
  2125. /*
  2126. ** Handler for processing temperature logs
  2127. */
  2128. PROC process_log_temperature(reply:PTR TO l_sense)
  2129.     outlist_i('\ebLog Size:\en', reply.len, ' bytes')
  2130.     outlist_i('\ebCurrent Temperature:\en', Char(reply+9),' degrees celsius')
  2131.     IF (reply.len > 15) THEN outlist_i('\ebReference Temperature:\en', Char(reply+15), ' degrees celsius')
  2132. ENDPROC
  2133.  
  2134. /*
  2135. ** Adds entries into the listview where both parameters are strings. The first
  2136. ** string is column one, the second is column two.
  2137. */
  2138. PROC outlist(str:PTR TO CHAR, str2:PTR TO CHAR)
  2139. DEF txt:listentry
  2140.  
  2141.     txt.field:=str
  2142.     txt.value:=str2
  2143.     txt.driver:=NIL
  2144.     txt.unit:=NIL
  2145.     doMethodA(mui_output_lst, [MUIM_List_InsertSingle, txt, MUIV_List_Insert_Bottom])
  2146. ENDPROC
  2147.  
  2148.  
  2149. /*
  2150. ** Adds entries into the listview where the first parameter is a string, the
  2151. ** second is an integer, and the third is an optional string. The first string
  2152. ** is column one, the integer is converted into a string and is column two.
  2153. ** In the case of the last string (if present) this is appended in column two
  2154. ** and is usually used for display a value type (eg bytes)
  2155. */
  2156. PROC outlist_i(str:PTR TO CHAR, int, valtype:PTR TO CHAR)
  2157. DEF txt:listentry,
  2158.     str2[80]:STRING
  2159.  
  2160.     IF valtype=NIL THEN StringF(str2, '\d', int) ELSE StringF(str2, '\d\s', int, valtype)
  2161.  
  2162.     txt.field:=str
  2163.     txt.value:=str2
  2164.     txt.driver:=NIL
  2165.     txt.unit:=NIL
  2166.     doMethodA(mui_output_lst, [MUIM_List_InsertSingle, txt, MUIV_List_Insert_Bottom])
  2167. ENDPROC
  2168.  
  2169.  
  2170. /*
  2171. ** Almost identical to outlist_i, except the integer is converted into Hex
  2172. ** before being made into a string
  2173. */
  2174. PROC outlist_h(str:PTR TO CHAR, int, valtype:PTR TO CHAR)
  2175. DEF txt:listentry,
  2176.     str2[80]:STRING
  2177.  
  2178.     IF valtype=NIL THEN StringF(str2, '$\h', int) ELSE StringF(str2, '$\h\s', int, valtype)
  2179.  
  2180.     txt.field:=str
  2181.     txt.value:=str2
  2182.     txt.driver:=NIL
  2183.     txt.unit:=NIL
  2184.     doMethodA(mui_output_lst, [MUIM_List_InsertSingle, txt, MUIV_List_Insert_Bottom])
  2185. ENDPROC
  2186.  
  2187.  
  2188. /*
  2189. ** This procedure adds special entries into the listview which the user may
  2190. ** double click. They have a specific format, with additional information
  2191. ** that is hidden from the display of the listview, but can be queried if
  2192. ** a user double clicks an entry.
  2193. */
  2194. PROC outlist_d(str:PTR TO CHAR, driver:PTR TO CHAR, unit)
  2195. DEF txt:listentry, buildstr[99]:STRING
  2196.  
  2197.     StringF(buildstr, '\eb\s [\d]:\en', driver, unit)
  2198.     txt.field:=buildstr
  2199.     txt.value:=str
  2200.     txt.driver:=driver
  2201.     txt.unit:=unit
  2202.     doMethodA(mui_output_lst, [MUIM_List_InsertSingle, txt, MUIV_List_Insert_Bottom])
  2203. ENDPROC
  2204.  
  2205.  
  2206. /*
  2207. ** The display hook for the listview. Entries are processed from an object
  2208. ** and insert into the appropriate columns
  2209. */
  2210. PROC disp(hook:PTR TO LONG, array:PTR TO LONG, entry:PTR TO listentry)
  2211.  
  2212.     IF entry=NIL -> MUI means update the titles whenever entry=NIL
  2213.         array[0]:='\eb\eu\ecField\en'
  2214.         array[1]:='\eb\eu\ecValue\en'
  2215.     ELSE
  2216.         array[0]:=entry.field
  2217.         array[1]:=entry.value
  2218.     ENDIF
  2219.  
  2220. ENDPROC 0
  2221.  
  2222.  
  2223. /*
  2224. ** The construction hook for the listview. Memory needs to be reserved
  2225. ** somewhere for each entry added, because only a pointer to a string actually
  2226. ** gets inserted. This copies each string into memory reserved from a pool. The
  2227. ** strings HAVE to be copied, as they will otherwise be freed by other
  2228. ** procedures, meaning the pointers in the listview would suddenly be invalid.
  2229. */
  2230. PROC construct (hook:PTR TO hook, pool:PTR TO LONG, obj:PTR TO listentry)
  2231. DEF value, field, driver=NIL, new:PTR TO listentry
  2232.  
  2233.     IF (field:=AllocPooled(pool, StrLen(obj.field)+1)) THEN CopyMem(obj.field, field, StrLen(obj.field)+1) -> +1 ensures NULL byte is copied
  2234.     IF (value:=AllocPooled(pool, StrLen(obj.value)+1)) THEN CopyMem(obj.value, value, StrLen(obj.value)+1) -> ditto
  2235.     IF obj.driver<>NIL
  2236.         IF (driver:=AllocPooled(pool, StrLen(obj.driver)+1)) THEN CopyMem(obj.driver, driver, StrLen(obj.driver)+1) -> ditto
  2237.     ENDIF
  2238.     new:=AllocPooled(pool, SIZEOF listentry)
  2239.     new.field:=field
  2240.     new.value:=value
  2241.     new.driver:=driver
  2242.     new.unit:=obj.unit
  2243. ENDPROC new
  2244.  
  2245.  
  2246. /*
  2247. ** Whenever an entry is removed from the listview, this procedure frees the
  2248. ** previously reserved memory for the strings.
  2249. */
  2250. PROC destruct (hook:PTR TO hook, pool:PTR TO LONG, obj:PTR TO listentry)
  2251.     FreePooled(pool, obj.field, StrLen(obj.field)+1)
  2252.     FreePooled(pool, obj.value, StrLen(obj.value)+1)
  2253.     IF obj.driver<>NIL THEN FreePooled(pool, obj.driver, StrLen(obj.driver)+1)
  2254.     FreePooled(pool, obj, SIZEOF listentry)
  2255. ENDPROC
  2256.  
  2257.  
  2258. /*
  2259. ** Simple macro procedure for making MUI buttons. Parameter 1 is the button
  2260. ** face, parameter 2 is the bubble help text. The buttons are automatically
  2261. ** added to the cycle chain
  2262. */
  2263. PROC make_button(face, bubble)
  2264. DEF button
  2265.  
  2266.     button:=SimpleButton(face)
  2267.     SetAttrsA(button, [MUIA_ShortHelp, bubble, MUIA_CycleChain, 1, TAG_DONE])
  2268. ENDPROC button
  2269.  
  2270.  
  2271. /*
  2272. ** Simple macro procedure for making cycle lists. Parameter 1 is an array of
  2273. ** the cycle contents, parameter 2 is the key which cycles it and parameter 3
  2274. ** is the bubble help test.
  2275. */
  2276. PROC make_keycycle(face, key, bubble)
  2277. DEF cycle
  2278.  
  2279.     cycle:=KeyCycle(face, key)
  2280.     SetAttrsA(cycle, [MUIA_ShortHelp, bubble, MUIA_CycleChain, 1, TAG_DONE])
  2281. ENDPROC cycle
  2282.  
  2283.  
  2284. /*
  2285. ** This procedure is called when the user double clicks and entry in the
  2286. ** listview. It queries the hidden data (as handled by outlist_d()) to
  2287. ** discover which device and unit to send the inquiry command to.
  2288. */
  2289. PROC click_inquiry()
  2290. DEF entry:PTR TO listentry, driver[99]:STRING, unit[4]:STRING
  2291.  
  2292.     doMethodA(mui_output_lst, [MUIM_List_GetEntry, MUIV_List_GetEntry_Active, {entry}])
  2293.     
  2294.     IF entry.driver <> NIL
  2295.         StrCopy(driver, entry.driver)
  2296.         StringF(unit, '\d', entry.unit)
  2297.         set(mui_device_tb, MUIA_String_Contents, driver)
  2298.         set(mui_unit_tb, MUIA_String_Contents, unit)
  2299.         doMethodA(mui_output_lst, [MUIM_List_Clear])
  2300.         query(driver, Val(unit), [SCSI_INQUIRY, 0, 0, 0, 36, 0]:cdb6, SIZEOF cdb6, AFLG_INQUIRY_VERBOSE)=0
  2301.     ENDIF
  2302. ENDPROC
  2303.  
  2304.  
  2305. /*
  2306. ** Procedure to fill an array with device drivers from the execlist. The array
  2307. ** is used in the device driver poplist so the user can select one instead of
  2308. ** manually typing it.
  2309. */
  2310. PROC grab_devices()
  2311. DEF i=0, devnode:PTR TO ln, devlist:PTR TO lh, d[99]:STRING
  2312.  
  2313.     -> NOTE. This might need placing inside a Forbid()/Permit() pair but
  2314.     -> I'm not entirely certain about that.
  2315.     execobject:=execbase
  2316.     devlist:=execobject.devicelist
  2317.     devnode:=devlist.head
  2318.  
  2319.     WHILE devnode.succ
  2320.         StrCopy(d, devnode.name)
  2321.         IF StrCmp(d, 'audio.device')=TRUE           -> We only filter out
  2322.         ELSEIF StrCmp(d, 'audio.device')=TRUE       -> standard AmigaOS
  2323.         ELSEIF StrCmp(d, 'timer.device')=TRUE       -> drivers which are not
  2324.         ELSEIF StrCmp(d, 'gameport.device')=TRUE    -> appropriate because
  2325.         ELSEIF StrCmp(d, 'keyboard.device')=TRUE    -> filtering a large
  2326.         ELSEIF StrCmp(d, 'console.device')=TRUE     -> amount of drivers
  2327.         ELSEIF StrCmp(d, 'clipboard.device')=TRUE   -> would be expensive
  2328.         ELSEIF StrCmp(d, 'ramdrive.device')=TRUE    -> on slow CPUs.
  2329.         ELSEIF StrCmp(d, 'input.device')=TRUE
  2330.         ELSEIF StrCmp(d, 'trackdisk.device')=TRUE
  2331.         ELSEIF StrCmp(d, 'serial.device')=TRUE
  2332.         ELSEIF StrCmp(d, 'printer.device')=TRUE
  2333.         ELSEIF StrCmp(d, 'parallel.device')=TRUE
  2334.         ELSE
  2335.             devicelist[i]:=devnode.name
  2336.             i++
  2337.         ENDIF
  2338.         devnode:=devnode.succ
  2339.     ENDWHILE
  2340.     devicelist[i]:='tcpip-scsi.device'
  2341.     i++
  2342.     devicelist[i]:=NIL
  2343.  
  2344. ENDPROC
  2345.